diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..16112797 Binary files /dev/null and b/.DS_Store differ diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 00000000..1db0cf8c --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,222 @@ +{ + "files": [ + "ALLCONTRIBUTOR.md" + ], + "imageSize": 100, + "commit": false, + "contributors": [ + { + "login": "webankadmin", + "name": "webankadmin", + "avatar_url": "https://avatars2.githubusercontent.com/u/43233241?v=4", + "profile": "https://github.com/webankadmin", + "contributions": [ + "business" + ] + }, + { + "login": "aleexzhang", + "name": "junqizhang", + "avatar_url": "https://avatars1.githubusercontent.com/u/3457149?v=4", + "profile": "https://github.com/aleexzhang", + "contributions": [ + "maintenance" + ] + }, + { + "login": "chenhaozx", + "name": "chenhaozx", + "avatar_url": "https://avatars3.githubusercontent.com/u/34266296?v=4", + "profile": "https://github.com/chenhaozx", + "contributions": [ + "maintenance" + ] + }, + { + "login": "chaoxinhu", + "name": "chaoxinhu", + "avatar_url": "https://avatars2.githubusercontent.com/u/44358688?v=4", + "profile": "https://github.com/chaoxinhu", + "contributions": [ + "maintenance" + ] + }, + { + "login": "chent57", + "name": "chent57", + "avatar_url": "https://avatars2.githubusercontent.com/u/53847508?v=4", + "profile": "https://github.com/chent57", + "contributions": [ + "maintenance" + ] + }, + { + "login": "darwindu", + "name": "darwindu", + "avatar_url": "https://avatars0.githubusercontent.com/u/30070842?v=4", + "profile": "https://github.com/darwindu", + "contributions": [ + "maintenance" + ] + }, + { + "login": "yg3630536", + "name": "杨刚", + "avatar_url": "https://avatars2.githubusercontent.com/u/39685280?v=4", + "profile": "https://github.com/yg3630536", + "contributions": [ + "maintenance" + ] + }, + { + "login": "anyspa", + "name": "anyspa", + "avatar_url": "https://avatars1.githubusercontent.com/u/35908094?v=4", + "profile": "https://github.com/anyspa", + "contributions": [ + "maintenance" + ] + }, + { + "login": "chirdxing", + "name": "chirdxing", + "avatar_url": "https://avatars1.githubusercontent.com/u/26427952?v=4", + "profile": "https://github.com/chirdxing", + "contributions": [ + "code" + ] + }, + { + "login": "hupeng199", + "name": "hupeng", + "avatar_url": "https://avatars2.githubusercontent.com/u/44767623?v=4", + "profile": "https://github.com/hupeng199", + "contributions": [ + "code" + ] + }, + { + "login": "chenqping", + "name": "chenqping", + "avatar_url": "https://avatars1.githubusercontent.com/u/5651810?v=4", + "profile": "http://weibo.com/u/2633029191/home?wvr=5&lf=reg#!/u/2633029191/home?leftnav=1&wvr=5", + "contributions": [ + "code" + ] + }, + { + "login": "chengzi8705", + "name": "chengzi8705", + "avatar_url": "https://avatars0.githubusercontent.com/u/12156175?v=4", + "profile": "https://github.com/chengzi8705", + "contributions": [ + "code" + ] + }, + { + "login": "The-Emperor1", + "name": "The-Emperor1", + "avatar_url": "https://avatars0.githubusercontent.com/u/23447833?v=4", + "profile": "https://github.com/The-Emperor1", + "contributions": [ + "code" + ] + }, + { + "login": "IdioticMadman", + "name": "robert", + "avatar_url": "https://avatars2.githubusercontent.com/u/16788980?v=4", + "profile": "https://github.com/IdioticMadman", + "contributions": [ + "code" + ] + }, + { + "login": "renranshengxia", + "name": "renranshengxia", + "avatar_url": "https://avatars3.githubusercontent.com/u/6888882?v=4", + "profile": "https://github.com/renranshengxia", + "contributions": [ + "code" + ] + }, + { + "login": "xinjiandong", + "name": "xinjiandong", + "avatar_url": "https://avatars2.githubusercontent.com/u/47093465?v=4", + "profile": "https://github.com/xinjiandong", + "contributions": [ + "code" + ] + }, + { + "login": "EasonRyu", + "name": "eason_ryu", + "avatar_url": "https://avatars2.githubusercontent.com/u/15207576?v=4", + "profile": "https://github.com/EasonRyu", + "contributions": [ + "code" + ] + }, + { + "login": "tyGavinZJU", + "name": "tyGavinZJU", + "avatar_url": "https://avatars3.githubusercontent.com/u/37820916?v=4", + "profile": "https://github.com/tyGavinZJU", + "contributions": [ + "code" + ] + }, + { + "login": "Bingyy", + "name": "Bing", + "avatar_url": "https://avatars3.githubusercontent.com/u/7068217?v=4", + "profile": "https://bingw.blog.csdn.net/", + "contributions": [ + "code" + ] + }, + { + "login": "SherLzp", + "name": "Lin", + "avatar_url": "https://avatars0.githubusercontent.com/u/17902244?v=4", + "profile": "https://sher.vip", + "contributions": [ + "code" + ] + }, + { + "login": "QibingLee", + "name": "QibingLee", + "avatar_url": "https://avatars2.githubusercontent.com/u/45893591?v=4", + "profile": "https://github.com/QibingLee", + "contributions": [ + "code" + ] + }, + { + "login": "lecire", + "name": "Eric Chan", + "avatar_url": "https://avatars2.githubusercontent.com/u/971641?v=4", + "profile": "https://github.com/lecire", + "contributions": [ + "code" + ] + }, + { + "login": "RobinLG", + "name": "Robin Liu", + "avatar_url": "https://avatars0.githubusercontent.com/u/41276823?v=4", + "profile": "http://roliu.work", + "contributions": [ + "code" + ] + } + ], + "contributorsPerLine": 6, + "projectName": "WeIdentity", + "projectOwner": "chaoxinhu", + "repoType": "github", + "repoHost": "https://github.com", + "skipCi": true +} diff --git a/.ci/ca.crt b/.ci/ca.crt new file mode 100644 index 00000000..e69de29b diff --git a/.ci/script/build-ci.sh b/.ci/script/build-ci.sh new file mode 100644 index 00000000..c77e73b9 --- /dev/null +++ b/.ci/script/build-ci.sh @@ -0,0 +1,154 @@ +#!/bin/bash +java_source_code_dir=$(pwd) + +app_xml_config_tpl=${java_source_code_dir}/src/main/resources/fisco.properties.tpl +app_xml_config=${java_source_code_dir}/src/main/resources/fisco.properties +weid_config_tpl=${java_source_code_dir}/src/main/resources/weidentity.properties.tpl +weid_config=${java_source_code_dir}/src/main/resources/weidentity.properties + +export MYSQL_ADDRESS=${1:-0.0.0.0:3306} +export MYSQL_DATABASE=${2:-database} +export MYSQL_USERNAME=${3:-username} +export MYSQL_PASSWORD=${4:-mysqlPassword} +export REDIS_ADDRESS=${5:-0.0.0.0:6379} +export REDIS_PASSWORD=${6:-redisPassword} +export PERSISTENCE_TYPE=${7:-type} + +JAVA_OPTS='-Djdk.tls.namedGroups="secp256r1,secp256k1"' + +function modify_config() +{ + echo "begin to modify sdk config..." + + export FISCO_BCOS_VERSION=${FISCO_BCOS_VERSION} + export CNS_PROFILE_ACTIVE=${CNS_PROFILE_ACTIVE} + + MYVARS='${FISCO_BCOS_VERSION}:${CNS_PROFILE_ACTIVE}' + envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} + cp ${app_xml_config} ${java_source_code_dir}/src/test/resources/ + # cat $app_xml_config + + export ORG_ID=${ORG_ID} + export AMOP_ID=${AMOP_ID} + export MYSQL_ADDRESS=${MYSQL_ADDRESS} + export MYSQL_DATABASE=${MYSQL_DATABASE} + export MYSQL_USERNAME=${MYSQL_USERNAME} + export MYSQL_PASSWORD=${MYSQL_PASSWORD} + export REDIS_ADDRESS=${REDIS_ADDRESS} + export REDIS_PASSWORD=${REDIS_PASSWORD} + export PERSISTENCE_TYPE=${PERSISTENCE_TYPE} + export BLOCKCHIAN_NODE_INFO=${BLOCKCHIAN_NODE_INFO} + + NODEVAR='${ORG_ID}:${AMOP_ID}:${MYSQL_ADDRESS}:${MYSQL_DATABASE}:${MYSQL_USERNAME}:${MYSQL_PASSWORD}:${REDIS_ADDRESS}:${REDIS_PASSWORD}:${PERSISTENCE_TYPE}:${BLOCKCHIAN_NODE_INFO}' + envsubst ${NODEVAR} < ${weid_config_tpl} >${weid_config} + cp ${weid_config} ${java_source_code_dir}/src/test/resources/ + + if [ -e ${java_source_code_dir}/ecdsa_key ];then + cp ${java_source_code_dir}/ecdsa_key ${java_source_code_dir}/src/test/resources/ + fi + cp ${java_source_code_dir}/.ci/ca.crt ${java_source_code_dir}/src/test/resources + cp ${java_source_code_dir}/.ci/sdk.crt ${java_source_code_dir}/src/test/resources + cp ${java_source_code_dir}/.ci/sdk.key ${java_source_code_dir}/src/test/resources + cp ${java_source_code_dir}/NotoSansCJKtc-Regular.ttf ${java_source_code_dir}/src/main/resources + cp ${java_source_code_dir}/NotoSansCJKtc-Regular.ttf ${java_source_code_dir}/src/test/resources + cp -r ${java_source_code_dir}/src/main/resources/WeDPR_dynamic_lib ${java_source_code_dir}/src/test/resources + echo "modify sdk config finished..." +} + + +function gradle_build_sdk() +{ + #run gradle build + cp ${java_source_code_dir}/.ci/ca.crt ${java_source_code_dir}/src/main/resources + cp ${java_source_code_dir}/.ci/sdk.crt ${java_source_code_dir}/src/main/resources + cp ${java_source_code_dir}/.ci/sdk.key ${java_source_code_dir}/src/main/resources + + export FISCO_BCOS_VERSION="2" + export CNS_PROFILE_ACTIVE="ci" + + MYVARS='${FISCO_BCOS_VERSION}:${CNS_PROFILE_ACTIVE}' + envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} + + + content="$NODE_IP" + # content="0.0.0.0:8902" + export BLOCKCHIAN_NODE_INFO=${content} + export ORG_ID="webank_ci" + export AMOP_ID="amop_ci" + echo $MYSQL_ADDRESS + echo $MYSQL_DATABASE + echo $MYSQL_USERNAME + echo $MYSQL_PASSWORD + echo $REDIS_ADDRESS + echo $REDIS_PASSWORD + echo $PERSISTENCE_TYPE + NODEVAR='${ORG_ID}:${AMOP_ID}:${MYSQL_ADDRESS}:${MYSQL_DATABASE}:${MYSQL_USERNAME}:${MYSQL_PASSWORD}:${REDIS_ADDRESS}:${REDIS_PASSWORD}:${PERSISTENCE_TYPE}:${BLOCKCHIAN_NODE_INFO}' + envsubst ${NODEVAR} < ${weid_config_tpl} >${weid_config} + + echo "Begin to compile java code......" + if [ -d ${java_source_code_dir}/dist ]; then + rm -rf ${java_source_code_dir}/dist + fi + gradle clean build -x test + echo "compile java code done." +} + +function check() +{ + echo "begin check-info..." + chmod u+x check-info.sh + ./check-info.sh + echo "check-info done." +} + +function deploy_contract() +{ + + CLASSPATH=${java_source_code_dir}/dist/conf + echo "begin to deploy contract..." + for jar_file in ${java_source_code_dir}/dist/lib/*.jar + do + CLASSPATH=${CLASSPATH}:${jar_file} + done + for jar_file in ${java_source_code_dir}/dist/app/*.jar + do + CLASSPATH=${CLASSPATH}:${jar_file} + done + + chain_id=101 + privateKey=18602059553666200379844734388296903882431291027699519961839765914892609749994 + + java ${JAVA_OPTS} -cp "$CLASSPATH" com.webank.weid.contract.deploy.DeployContract ${chain_id} ${privateKey} + echo "contract deployment done." +} + +function install_font() +{ + # download NotoSansCJKtc-Regular.ttf + if [ ! -f NotoSansCJKtc-Regular.ttf ]; then + wget -c https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeIdentity/NotoSansCJKtc-Regular.ttf + fi + + if [ -f NotoSansCJKtc-Regular.ttf ]; then + sudo mkdir -p /usr/share/fonts/custom&& + sudo cp NotoSansCJKtc-Regular.ttf /usr/share/fonts/custom/&& + sudo apt install xfonts-utils -y&& + sudo mkfontscale&& + sudo mkfontdir&& + sudo fc-cache -fv + echo "font install done." + else + echo "font install fail." + fi +} + +function main() +{ + gradle_build_sdk + install_font + check + deploy_contract + modify_config +} + +main \ No newline at end of file diff --git a/.ci/script/weid-build-tools/build-ci.sh b/.ci/script/weid-build-tools/build-ci.sh new file mode 100644 index 00000000..5bb00125 --- /dev/null +++ b/.ci/script/weid-build-tools/build-ci.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env sh + +if [ "$TRAVIS_BRANCH" = "master" ];then + echo "This is a master branch PR, starting build-tools CI pipeline.." + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh + + # clone repo + rm -rf weid-build-tools/ + git clone https://github.com/WeBankFinTech/weid-build-tools.git + cd weid-build-tools + git checkout master + cd .. + + # construct SDK jar version and file name + cat build.gradle | grep "version =" > temp.ver + sed -e "s/version = \"//g" -i temp.ver + sed -e "s/\"//g" -i temp.ver + SDKVER=$(cat temp.ver) + rm temp.ver + SDKNAME='weid-java-sdk-' + JAR='.jar' + FILENAME="$SDKNAME$SDKVER$JAR" + echo sdk jar filename: $FILENAME + + # copy SDK jar to repo dependencies path and rename + # requires repo to allow local dep first + mkdir -p weid-build-tools/dependencies + cp dist/app/$FILENAME weid-build-tools/dependencies/weid-java-sdk-pipeline.jar + mkdir -p weid-build-tools/dist/lib + cp dist/lib/* weid-build-tools/dist/lib/ + + # install fisco-solc + wget https://github.com/FISCO-BCOS/fisco-solc/raw/master/fisco-solc-ubuntu + sudo cp fisco-solc-ubuntu /usr/bin/fisco-solc + sudo chmod u+x /usr/bin/fisco-solc + + # copy blockchain cfg files + cp .ci/ca.crt weid-build-tools/resources/ + cp .ci/sdk.crt weid-build-tools/resources/ + cp .ci/sdk.key weid-build-tools/resources/ + + # run repo ci scripts + cd weid-build-tools/ + sed -i -e '$a\org_id=test' run.config + sed -i -e '$a\blockchain_address=$NODE_IP' run.config + chmod u+x compile.sh + ./compile.sh + chmod u+x deploy.sh + ./deploy.sh + cp ./script/build_tools_ci.sh . + chmod u+x build_tools_ci.sh + ./build_tools_ci.sh +else + echo "This is not a master branch PR (commit omitted). CI skipped." +fi \ No newline at end of file diff --git a/.ci/script/weid-http-service/build-ci.sh b/.ci/script/weid-http-service/build-ci.sh new file mode 100644 index 00000000..7e7a60c4 --- /dev/null +++ b/.ci/script/weid-http-service/build-ci.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env sh + +if [ "$TRAVIS_BRANCH" = "master" ];then + echo "This is a master branch PR, starting Http Service CI pipeline.." + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh + + # clone repo + rm -rf weid-http-service/ + git clone https://github.com/WeBankFinTech/weid-http-service.git + + # construct SDK jar version and file name + cat build.gradle | grep "version =" > temp.ver + sed -e "s/version = \"//g" -i temp.ver + sed -e "s/\"//g" -i temp.ver + SDKVER=$(cat temp.ver) + rm temp.ver + SDKNAME='weid-java-sdk-' + JAR='.jar' + FILENAME="$SDKNAME$SDKVER$JAR" + echo sdk jar filename: $FILENAME + + # copy SDK jar and libs to repo dependencies path and rename + cp dist/app/$FILENAME weid-http-service/dependencies/weid-java-sdk-pipeline.jar + mkdir -p weid-http-service/dist/lib + cp dist/lib/* weid-http-service/dist/lib/ + + # copy config files + cp ecdsa_key weid-http-service/src/main/resources/ + cp ecdsa_key weid-http-service/src/test/resources/ + cp ecdsa_key weid-http-service/keys/priv/ + cp src/main/resources/* weid-http-service/src/main/resources/ + cp src/main/resources/* weid-http-service/src/test/resources/ + cp .ci/ca.crt weid-http-service/src/test/resources/ + cp .ci/ca.crt weid-http-service/src/main/resources/ + cp .ci/sdk.crt weid-http-service/src/test/resources/ + cp .ci/sdk.crt weid-http-service/src/main/resources/ + cp .ci/sdk.key weid-http-service/src/test/resources/ + cp .ci/sdk.key weid-http-service/src/main/resources/ + + # run repo ci scripts + cd weid-http-service/ + #gradle build +else + echo "This is not a master branch PR (commit omitted). Http Service CI skipped." +fi \ No newline at end of file diff --git a/.ci/script/weid-sample/build-ci.sh b/.ci/script/weid-sample/build-ci.sh new file mode 100644 index 00000000..9eb85ca3 --- /dev/null +++ b/.ci/script/weid-sample/build-ci.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env sh + +if [ "$TRAVIS_BRANCH" = "master" ];then + echo "This is a master branch PR, starting Sample CI pipeline.." + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh + + # clone repo + rm -rf weid-sample/ + git clone https://github.com/WeBankFinTech/weid-sample.git + cd weid-sample/ + git checkout develop + cd .. + + # construct SDK jar version and file name + cat build.gradle | grep "version =" > temp.ver + sed -e "s/version = \"//g" -i temp.ver + sed -e "s/\"//g" -i temp.ver + SDKVER=$(cat temp.ver) + rm temp.ver + SDKNAME='weid-java-sdk-' + JAR='.jar' + FILENAME="$SDKNAME$SDKVER$JAR" + echo sdk jar filename: $FILENAME + + # copy SDK jar to repo dependencies path and rename + # requires repo to allow local dep first + mkdir -p weid-sample/dependencies + cp dist/app/$FILENAME weid-sample/dependencies/weid-java-sdk-pipeline.jar + mkdir -p weid-sample/libs + cp dist/lib/* weid-sample/libs + + # copy config files + cp ecdsa_key weid-sample/keys/priv/ + cp src/main/resources/fisco.properties weid-sample/src/main/resources/ + cp src/main/resources/weidentity.properties weid-sample/src/main/resources/ + cp .ci/ca.crt weid-sample/src/main/resources/ + cp .ci/sdk.crt weid-sample/src/main/resources/ + cp .ci/sdk.key weid-sample/src/main/resources/ + + # run repo ci scripts + cd weid-sample/ + chmod u+x *.sh + #./build.sh + + #if ! ./sample-ci.sh + #then + #echo "execute sample-ci failed." + #exit 1 + #fi + + echo "execute sample-ci success." + #gradle build +else + echo "This is not a master branch PR (commit omitted). CI skipped." +fi \ No newline at end of file diff --git a/.ci/sdk.crt b/.ci/sdk.crt new file mode 100644 index 00000000..473d6ae7 --- /dev/null +++ b/.ci/sdk.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIBeDCCAR6gAwIBAgIJALkdvuWSdhvfMAoGCCqGSM49BAMCMDcxDzANBgNVBAMM +BmFnZW5jeTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5MCAX +DTIyMDMyMzA5MTM0NFoYDzIxMjIwMjI3MDkxMzQ0WjAxMQwwCgYDVQQDDANzZGsx +EzARBgNVBAoMCmZpc2NvLWJjb3MxDDAKBgNVBAsMA3NkazBWMBAGByqGSM49AgEG +BSuBBAAKA0IABEhQrhgxPHQIGOW7V12Jv+7BzKnheZYPIPbqMR/993QGKqk/5u3+ +FyVE2xEGlXa/agLUU2JhmD9yH3nlKR/agfWjGjAYMAkGA1UdEwQCMAAwCwYDVR0P +BAQDAgXgMAoGCCqGSM49BAMCA0gAMEUCIFzn+OXMvv8yD3jzKjb7ccLfPMoUxUZB +pHHmaeaxfamBAiEA6vK2UJivk2j1bxV3NnqTKtDqCwzRHkEAD55iId/mU50= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBcDCCARagAwIBAgIJAKybOwjnSONHMAoGCCqGSM49BAMCMDUxDjAMBgNVBAMM +BWNoYWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAeFw0y +MjAzMjMwOTEzNDRaFw0zMjAzMjAwOTEzNDRaMDcxDzANBgNVBAMMBmFnZW5jeTET +MBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5MFYwEAYHKoZIzj0C +AQYFK4EEAAoDQgAEtaOfgPeNxIkIftVUjvOccocHx4LWnr8lIyT62IKNQPXtDi8U +cJ/0ZaO1btA9lBP4v7YYXVS08iAPvbwwkd002aMQMA4wDAYDVR0TBAUwAwEB/zAK +BggqhkjOPQQDAgNIADBFAiEA1bFbIlVgMr7pbS1VO4UgMnVSPKt1M5115niCdgfU +b1UCIHXSu/stpU+2FWD6HwKRWZQ7VQu/m3qxWpg/+a/S/roM +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBVzCB/wIJAKoq+vyUmlMJMAoGCCqGSM49BAMCMDUxDjAMBgNVBAMMBWNoYWlu +MRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAgFw0yMjAzMjMw +OTEzNDRaGA8yMTIyMDIyNzA5MTM0NFowNTEOMAwGA1UEAwwFY2hhaW4xEzARBgNV +BAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMFYwEAYHKoZIzj0CAQYFK4EE +AAoDQgAEZC0Gxxlvd4jLugWP/usLPQYWvXYWjMHSwF/U2ZQeYklf85r3GaqP6HV2 +yEnvDuaemDxMPItzy5cHzjfSBrif5TAKBggqhkjOPQQDAgNHADBEAiA4or46kQ4R +IKQZQyjbL+JvHsj5nMLyaHe4esX9xRVwTQIgI0P7B7XJd8qX8qZqgp2hWbVNdtN/ +7W1/jYj/9NjJysE= +-----END CERTIFICATE----- diff --git a/.ci/sdk.key b/.ci/sdk.key new file mode 100644 index 00000000..d95ed42c --- /dev/null +++ b/.ci/sdk.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgsT4z8MIQvU/QnUhRsz9b +YUx609vYlghhWRiyekMbIaChRANCAARIUK4YMTx0CBjlu1ddib/uwcyp4XmWDyD2 +6jEf/fd0BiqpP+bt/hclRNsRBpV2v2oC1FNiYZg/ch955Skf2oH1 +-----END PRIVATE KEY----- diff --git a/.gitchangelog.rc b/.gitchangelog.rc new file mode 100644 index 00000000..08fa071e --- /dev/null +++ b/.gitchangelog.rc @@ -0,0 +1,289 @@ +# -*- coding: utf-8; mode: python -*- +## +## Format +## +## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...] +## +## Description +## +## ACTION is one of 'chg', 'fix', 'new' +## +## Is WHAT the change is about. +## +## 'chg' is for refactor, small improvement, cosmetic changes... +## 'fix' is for bug fixes +## 'new' is for new features, big improvement +## +## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc' +## +## Is WHO is concerned by the change. +## +## 'dev' is for developpers (API changes, refactors...) +## 'usr' is for final users (UI changes) +## 'pkg' is for packagers (packaging changes) +## 'test' is for testers (test only related changes) +## 'doc' is for doc guys (doc only changes) +## +## COMMIT_MSG is ... well ... the commit message itself. +## +## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic' +## +## They are preceded with a '!' or a '@' (prefer the former, as the +## latter is wrongly interpreted in github.) Commonly used tags are: +## +## 'refactor' is obviously for refactoring code only +## 'minor' is for a very meaningless change (a typo, adding a comment) +## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...) +## 'wip' is for partial functionality but complete subfunctionality. +## +## Example: +## +## new: usr: support of bazaar implemented +## chg: re-indentend some lines !cosmetic +## new: dev: updated code to be compatible with last version of killer lib. +## fix: pkg: updated year of licence coverage. +## new: test: added a bunch of test around user usability of feature X. +## fix: typo in spelling my name in comment. !minor +## +## Please note that multi-line commit message are supported, and only the +## first line will be considered as the "summary" of the commit message. So +## tags, and other rules only applies to the summary. The body of the commit +## message will be displayed in the changelog without reformatting. + + +## +## ``ignore_regexps`` is a line of regexps +## +## Any commit having its full commit message matching any regexp listed here +## will be ignored and won't be reported in the changelog. +## +ignore_regexps = [ + r'@minor', r'!minor', + r'@cosmetic', r'!cosmetic', + r'@refactor', r'!refactor', + r'@wip', r'!wip', + r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', + r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', + r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', + r'^$', ## ignore commits with empty messages +] + + +## ``section_regexps`` is a list of 2-tuples associating a string label and a +## list of regexp +## +## Commit messages will be classified in sections thanks to this. Section +## titles are the label, and a commit is classified under this section if any +## of the regexps associated is matching. +## +## Please note that ``section_regexps`` will only classify commits and won't +## make any changes to the contents. So you'll probably want to go check +## ``subject_process`` (or ``body_process``) to do some changes to the subject, +## whenever you are tweaking this variable. +## +section_regexps = [ + ('New', [ + r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + ('Changes', [ + r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + ('Fix', [ + r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + + ('Other', None ## Match all lines + ), + +] + + +## ``body_process`` is a callable +## +## This callable will be given the original body and result will +## be used in the changelog. +## +## Available constructs are: +## +## - any python callable that take one txt argument and return txt argument. +## +## - ReSub(pattern, replacement): will apply regexp substitution. +## +## - Indent(chars=" "): will indent the text with the prefix +## Please remember that template engines gets also to modify the text and +## will usually indent themselves the text if needed. +## +## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns +## +## - noop: do nothing +## +## - ucfirst: ensure the first letter is uppercase. +## (usually used in the ``subject_process`` pipeline) +## +## - final_dot: ensure text finishes with a dot +## (usually used in the ``subject_process`` pipeline) +## +## - strip: remove any spaces before or after the content of the string +## +## - SetIfEmpty(msg="No commit message."): will set the text to +## whatever given ``msg`` if the current text is empty. +## +## Additionally, you can `pipe` the provided filters, for instance: +#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ") +#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') +#body_process = noop +body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip + + +## ``subject_process`` is a callable +## +## This callable will be given the original subject and result will +## be used in the changelog. +## +## Available constructs are those listed in ``body_process`` doc. +subject_process = (strip | + ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') | + SetIfEmpty("No commit message.") | ucfirst | final_dot) + + +## ``tag_filter_regexp`` is a regexp +## +## Tags that will be used for the changelog must match this regexp. +## +tag_filter_regexp = r'v^[0-9]+\.[0-9]+(\.[0-9]+)?$' + + +## ``unreleased_version_label`` is a string or a callable that outputs a string +## +## This label will be used as the changelog Title of the last set of changes +## between last valid tag and HEAD if any. +unreleased_version_label = "(unreleased)" + + +## ``output_engine`` is a callable +## +## This will change the output format of the generated changelog file +## +## Available choices are: +## +## - rest_py +## +## Legacy pure python engine, outputs ReSTructured text. +## This is the default. +## +## - mustache() +## +## Template name could be any of the available templates in +## ``templates/mustache/*.tpl``. +## Requires python package ``pystache``. +## Examples: +## - mustache("markdown") +## - mustache("restructuredtext") +## +## - makotemplate() +## +## Template name could be any of the available templates in +## ``templates/mako/*.tpl``. +## Requires python package ``mako``. +## Examples: +## - makotemplate("restructuredtext") +## +output_engine = rest_py +#output_engine = mustache("restructuredtext") +#output_engine = mustache("markdown") +#output_engine = makotemplate("restructuredtext") + + +## ``include_merge`` is a boolean +## +## This option tells git-log whether to include merge commits in the log. +## The default is to include them. +include_merge = False + + +## ``log_encoding`` is a string identifier +## +## This option tells gitchangelog what encoding is outputed by ``git log``. +## The default is to be clever about it: it checks ``git config`` for +## ``i18n.logOutputEncoding``, and if not found will default to git's own +## default: ``utf-8``. +#log_encoding = 'utf-8' + + +## ``publish`` is a callable +## +## Sets what ``gitchangelog`` should do with the output generated by +## the output engine. ``publish`` is a callable taking one argument +## that is an interator on lines from the output engine. +## +## Some helper callable are provided: +## +## Available choices are: +## +## - stdout +## +## Outputs directly to standard output +## (This is the default) +## +## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start()) +## +## Creates a callable that will parse given file for the given +## regex pattern and will insert the output in the file. +## ``idx`` is a callable that receive the matching object and +## must return a integer index point where to insert the +## the output in the file. Default is to return the position of +## the start of the matched string. +## +## - FileRegexSubst(file, pattern, replace, flags) +## +## Apply a replace inplace in the given file. Your regex pattern must +## take care of everything and might be more complex. Check the README +## for a complete copy-pastable example. +## +# publish = FileInsertIntoFirstRegexMatch( +# "CHANGELOG.rst", +# r'/(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n/', +# idx=lambda m: m.start(1) +# ) +#publish = stdout + + +## ``revs`` is a list of callable or a list of string +## +## callable will be called to resolve as strings and allow dynamical +## computation of these. The result will be used as revisions for +## gitchangelog (as if directly stated on the command line). This allows +## to filter exaclty which commits will be read by gitchangelog. +## +## To get a full documentation on the format of these strings, please +## refer to the ``git rev-list`` arguments. There are many examples. +## +## Using callables is especially useful, for instance, if you +## are using gitchangelog to generate incrementally your changelog. +## +## Some helpers are provided, you can use them:: +## +## - FileFirstRegexMatch(file, pattern): will return a callable that will +## return the first string match for the given pattern in the given file. +## If you use named sub-patterns in your regex pattern, it'll output only +## the string matching the regex pattern named "rev". +## +## - Caret(rev): will return the rev prefixed by a "^", which is a +## way to remove the given revision and all its ancestor. +## +## Please note that if you provide a rev-list on the command line, it'll +## replace this value (which will then be ignored). +## +## If empty, then ``gitchangelog`` will act as it had to generate a full +## changelog. +## +## The default is to use all commits to make the changelog. +#revs = ["^1.0.3", ] +#revs = [ +# Caret( +# FileFirstRegexMatch( +# "CHANGELOG.rst", +# r"(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n")), +# "HEAD" +#] +revs = [] diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..30376387 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# 如何贡献 + +--- + +非常感谢您对 WeIdentity 有兴趣。欢迎提交 Pull Request ,参与 bug 修复,文档优化,或者任何优化意见。 + +--- + +## 1. 发现 bug + +使用过程中遇到的任何问题,可以查看 [FAQ](https://weidentity.readthedocs.io/zh_CN/latest/docs/faq.html),或者给我们提 [issue](https://github.com/WeBankFinTech/WeIdentity/issues)。 + +## 2. 优化建议 + +有任何优化建议,欢迎给我们提 [issue](https://github.com/WeBankFinTech/WeIdentity/issues)。 + +--- + +## 3. 贡献代码 + +### 3.1 开始之前 + +请先浏览WeIdentity工程遵循的相关规范,包括分支管理,代码规范,commit规范。 + +#### 分支管理 + +代码类工程我们使用 [git-flow](https://nvie.com/posts/a-successful-git-branching-model/) 进行分支管理。包括这些工程: [WeIdentity](https://github.com/WeBankFinTech/WeIdentity),[weid-contract](https://github.com/WeBankFinTech/weid-contract),[weid-build-tools](https://github.com/WeBankFinTech/weid-build-tools),[weid-sample](https://github.com/WeBankFinTech/weid-sample)。 +文档类工程我们使用 [github-flow](http://scottchacon.com/2011/08/31/github-flow.html) 进行分支管理。包括这些工程:[weid-doc](https://github.com/WeBankFinTech/weid-doc)。 + +#### 代码规范 + +建议先浏览 [WeIdentity 代码规范](https://weidentity.readthedocs.io/zh_CN/latest/docs/styleguides/styleguides.html)。 + +#### 测试 + +所有提交的代码必须通过单元测试,如果提交的代码目前的单元测试用例无法覆盖,可以修改单元测试代码从而覆盖用例,或者在 Pull Request 里面说明情况,然后由我们来补充单元测试用例。详见“[如何运行单元测试](https://weidentity.readthedocs.io/zh_CN/latest/docs/how-to-run-unit-test.html)”。 + +#### Commit Messages + +使用英文简要描述修改点,每一行描述一个修改点,并以 `*` 开头,如下所示: + +```text +first release for weid-contract + +* Smart Contract for DID identity management, allowing external +addresses which satisfy FISCO-BCOS specifications to be used as the +identification tag. +* Smart Contract for Committee Membership management, including data & +logic contracts. +* Smart Contract for Authority Issuer Membership management, including +data & logic contracts. +``` + +--- + +### 3.2 流程 + +1. Fork 希望提交代码修改的 repository 。例如,如果想要修改 [WeIdentity](https://github.com/WeBankFinTech/WeIdentity) ,则 Fork 这个 repository。 + +2. 创建新的分支,例如分支取名为 `feature/add-verfiy-logic` (分支名请使用 `feature/` 开头)。 + + ```shell + git checkout -b feature/add-verfiy-logic + ``` + +3. 编写代码。 + +4. 运行单元测试(会自动运行单元测试,checkstyle,spotbugs)并通过。 + +5. Push 这个分支 `feature/verfiy-logic-bug-fix` 到自己的 repository。 + +6. 提交 Pull Request 到 repository 的 `develop` 分支, 并描述您的修改。例如描述修复的 bug,或者描述新增的功能(如果是较大的修改,建议在代码实现前提交一个[优化建议issue](https://github.com/WeBankFinTech/WeIdentity/issues),提前描述自己的设计)。并标记任意一个 maintainer 进行 review。 + +7. maintainer 完成review,合并您的 Pull Request 到 `develop` 分支,然后我们会在下一个发布时间点将其合并到 `master` 分支。感谢您的贡献。 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b8ced254..07430074 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -23,7 +23,6 @@ Describe what you expected to happen and what actually happened. ## Additional context #### Config Files -- FISCO-BCOS: Please refer to [FISCO-BCOS site](https://github.com/FISCO-BCOS/FISCO-BCOS) for more details. - WeIdentity: Grab them at /src/main/resources/. #### Log Files diff --git a/.github/ISSUE_TEMPLATE/bug_report_cn.md b/.github/ISSUE_TEMPLATE/bug_report_cn.md index 8b1bf41f..ddfd983d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_cn.md +++ b/.github/ISSUE_TEMPLATE/bug_report_cn.md @@ -23,7 +23,6 @@ about: 根据使用WeIdentity过程中发现的问题,提交一份错误报告 ## 其他内容 #### 配置文件 -- FISCO-BCOS: 请访问 [FISCO-BCOS官网](https://github.com/FISCO-BCOS/FISCO-BCOS) 以获得更多细节信息。 - WeIdentity: 请上传所有位于 /src/main/resources/ 目录下的文件。 #### 日志文件 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 00000000..14568a48 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,260 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: [ master ] + pull_request: + branches: [ master, develop, release/** ] + +jobs: + weid-java-sdk-ci: + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 3 + - name: Start Redis Server + uses: karenlrx/redis-github-action@1.2.0 + with: + redis-version: 5 + - name: Verify Redis connection + run: | + sudo docker exec redis redis-cli -p 6379 -a 123456 ping + - name: Verify MySQL connection and create CI DB + run: | + sudo systemctl start mysql.service + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'CREATE DATABASE IF NOT EXISTS cidb;' + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'show databases;' + - name: Prepare blockchain nodes and certificates + run: | + mkdir -p fisco && cd fisco + curl -LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.7.1/build_chain.sh && chmod u+x build_chain.sh + bash build_chain.sh -l "127.0.0.1:2" -p 30300,20200,8545 + bash nodes/127.0.0.1/start_all.sh + ps -ef | grep -v grep | grep fisco + cd .. + cp ./fisco/nodes/127.0.0.1/sdk/* ./.ci/ + - name: Prepare gradle + uses: eskatos/gradle-command-action@v1 + with: + gradle-version: 5.6 + - name: source-code deployment + run: | + export NODE_IP=127.0.0.1:20200 + export NODE2_IP=127.0.0.1:20201 + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh 127.0.0.1:3306 cidb root root 127.0.0.1:6379 123456 redis + - name: Run CI + run: | + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + gradle check -i + gradle jacocoTestReport + bash <(curl -s https://codecov.io/bash) + - name: Download failed log (if any) + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: sdk-log + path: /home/runner/work/WeIdentity/WeIdentity/build/reports/ + weid-sample-ci: + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 3 + - name: Verify MySQL connection and create CI DB + run: | + sudo systemctl start mysql.service + sudo apt-get install -y mysql-client + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'CREATE DATABASE IF NOT EXISTS cidb;' + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'show databases;' + - name: Prepare blockchain nodes and certificates + run: | + mkdir -p fisco && cd fisco + curl -LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.7.1/build_chain.sh && chmod u+x build_chain.sh + bash build_chain.sh -l "127.0.0.1:2" -p 30300,20200,8545 + bash nodes/127.0.0.1/start_all.sh + ps -ef | grep -v grep | grep fisco + cd .. + cp ./fisco/nodes/127.0.0.1/sdk/* ./.ci/ + - name: Prepare gradle + uses: eskatos/gradle-command-action@v1 + with: + gradle-version: 5.6 + - name: source-code deployment + run: | + export NODE_IP=127.0.0.1:20200 + export NODE2_IP=127.0.0.1:20201 + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh 127.0.0.1:3306 cidb root root 127.0.0.1:6379 123456 redis + - name: Checkout and prepare + run: | + git clone https://github.com/WeBankFinTech/weid-sample.git + cd weid-sample + git checkout develop + cd .. + mkdir -p weid-sample/dependencies + cp dist/app/*.jar weid-sample/dependencies/weid-java-sdk-pipeline.jar + mkdir -p weid-sample/libs + cp dist/lib/*.jar weid-sample/libs/ + cp ecdsa_key weid-sample/keys/priv/ + cp src/main/resources/fisco.properties weid-sample/resources/ + cp src/main/resources/weidentity.properties weid-sample/resources/ + cp .ci/ca.crt weid-sample/resources/ + cp .ci/node.crt weid-sample/resources/ + cp .ci/node.key weid-sample/resources/ + - name: Run CI + run: | + cd weid-sample + chmod u+x *.sh + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + export NODE_IP=127.0.0.1:20200 + export NODE2_IP=127.0.0.1:20201 + ./build.sh + - name: Download failed log (if any) + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: sample-log + path: /home/runner/work/WeIdentity/WeIdentity/weid-sample/build/reports/ + weid-http-service-ci: + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 3 + - name: Verify MySQL connection and create CI DB + run: | + sudo systemctl start mysql.service + sudo apt-get install -y mysql-client + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'CREATE DATABASE IF NOT EXISTS cidb;' + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'show databases;' + - name: Prepare blockchain nodes and certificates + run: | + mkdir -p fisco && cd fisco + curl -LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.7.1/build_chain.sh && chmod u+x build_chain.sh + bash build_chain.sh -l "127.0.0.1:2" -p 30300,20200,8545 + bash nodes/127.0.0.1/start_all.sh + ps -ef | grep -v grep | grep fisco + cd .. + cp ./fisco/nodes/127.0.0.1/sdk/* ./.ci/ + - name: Prepare gradle + uses: eskatos/gradle-command-action@v1 + with: + gradle-version: 5.6 + - name: source-code deployment + run: | + export NODE_IP=127.0.0.1:20200 + export NODE2_IP=127.0.0.1:20201 + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh 127.0.0.1:3306 cidb root root + - name: Checkout and prepare + run: | + git clone https://github.com/WeBankFinTech/weid-http-service.git + cp dist/app/*.jar weid-http-service/dependencies/weid-java-sdk-pipeline.jar + mkdir -p weid-http-service/libs + cp dist/lib/* weid-http-service/libs + cp ecdsa_key weid-http-service/src/main/resources/ && cp ecdsa_key weid-http-service/src/test/resources/ && cp ecdsa_key weid-http-service/keys/priv/ && cp ecdsa_key weid-http-service/dist/keys/priv/ + cp src/main/resources/fisco.properties weid-http-service/src/main/resources/ + cp src/main/resources/fisco.properties weid-http-service/src/test/resources/ + cp src/main/resources/weidentity.properties weid-http-service/src/main/resources/ + cp src/main/resources/weidentity.properties weid-http-service/src/test/resources/ + cp .ci/ca.crt weid-http-service/src/test/resources/ + cp .ci/ca.crt weid-http-service/src/main/resources/ + cp .ci/node.crt weid-http-service/src/test/resources/ + cp .ci/node.crt weid-http-service/src/main/resources/ + cp .ci/node.key weid-http-service/src/test/resources/ + cp .ci/node.key weid-http-service/src/main/resources/ + - name: Run CI + run: | + cd weid-http-service/ + export PATH=/home/runner/gradle-installations/installs/gradle-5.6.1/bin:$PATH + ls -ll libs + gradle clean build -i -x test + - name: Download failed log (if any) + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: http-service-log + path: /home/runner/work/WeIdentity/WeIdentity/weid-http-service/build/reports/ + weid-build-tools-ci: + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 3 + - name: Verify MySQL connection and create CI DB + run: | + sudo systemctl start mysql.service + sudo apt-get install -y mysql-client + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'CREATE DATABASE IF NOT EXISTS cidb;' + mysql --host=127.0.0.1 --port=3306 --user=root --password=root -e 'show databases;' + - name: Prepare blockchain nodes and certificates + run: | + mkdir -p fisco && cd fisco + curl -LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.7.1/build_chain.sh && chmod u+x build_chain.sh + bash build_chain.sh -l "127.0.0.1:2" -p 30300,20200,8545 + bash nodes/127.0.0.1/start_all.sh + ps -ef | grep -v grep | grep fisco + cd .. + cp ./fisco/nodes/127.0.0.1/sdk/* ./.ci/ + - name: Prepare gradle + uses: eskatos/gradle-command-action@v1 + with: + gradle-version: 5.6 + - name: source-code deployment + run: | + export NODE_IP=127.0.0.1:20200 + export NODE2_IP=127.0.0.1:20201 + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + chmod u+x .ci/script/build-ci.sh + .ci/script/build-ci.sh 127.0.0.1:3306 cidb root root + - name: Checkout and prepare + run: | + git clone https://github.com/WeBankFinTech/weid-build-tools.git + mkdir -p weid-build-tools/dependencies + cp dist/app/*.jar weid-build-tools/dependencies/weid-java-sdk-pipeline.jar + wget https://github.com/FISCO-BCOS/fisco-solc/raw/master/fisco-solc-ubuntu + sudo cp fisco-solc-ubuntu /usr/bin/fisco-solc + sudo chmod u+x /usr/bin/fisco-solc + cp .ci/ca.crt weid-build-tools/resources/ + cp .ci/node.crt weid-build-tools/resources/ + cp .ci/node.key weid-build-tools/resources/ + - name: Run CI + run: | + cd weid-build-tools/ + export PATH=/home/runner/gradle-installations/installs/gradle-5.6/bin:$PATH + sed -i -e '$a\org_id=test' run.config + sed -i -e '$a\amop_id=test' run.config + sed -i -e '$a\blockchain_address=127.0.0.1:20200' run.config + sed -i -e '$a\mysql_address=127.0.0.1:3306' run.config + sed -i -e '$a\mysql_database=cidb' run.config + sed -i -e '$a\mysql_username=root' run.config + sed -i -e '$a\mysql_password=root' run.config + chmod u+x compile.sh + ./compile.sh + chmod u+x deploy.sh + ./deploy.sh + cp ./common/script/build_tools_ci.sh . + chmod u+x build_tools_ci.sh + ./build_tools_ci.sh + - name: Download failed log (if any) + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: build-tools-log + path: /home/runner/work/WeIdentity/WeIdentity/weid-build-tools/build/reports/ diff --git a/.gitignore b/.gitignore index 93e1f542..a9f135d1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ Created by https://www.gitignore.io/api/vim,java,maven,gradle,java-web,intellij, .idea/**/workspace.xml .idea/**/tasks.xml .idea/dictionaries - +.idea/checkstyle-idea.xml # Sensitive or high-churn files: .idea/**/dataSources/ .idea/**/dataSources.ids @@ -22,6 +22,9 @@ Created by https://www.gitignore.io/api/vim,java,maven,gradle,java-web,intellij, .idea/**/gradle.xml .idea/**/libraries +.idea/*.xml +.idea/vcs.xml + # CMake cmake-build-debug/ @@ -176,7 +179,6 @@ build.tar.gz .rsync.sh rsync.ex build/ -dist/ bak/ *docx *pdf @@ -191,3 +193,10 @@ doc/bak/ .settings/ .project .classpath +.idea/ +/dist/ + +secring.gpg +*.address +logs/ +gradle.properties \ No newline at end of file diff --git a/.one-button-release/auto_release.sh b/.one-button-release/auto_release.sh new file mode 100644 index 00000000..adfff6d4 --- /dev/null +++ b/.one-button-release/auto_release.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -e +[ -z "$DEBUG" ] || set -x; + +# SYNTAX: +# $ ./auto-release.sh +# EXAMPLE: +# $ ./auto-release.sh WeBankFinTech/WeIdentity v1.5.0 v1.4.1 +# +# Prerequisites: +# 1. Fill in signing and OSS account info in gradle.properties +# 2. pip install gitchangelog +# 3. Finish your CHANGELOG.md and also FINISHED MERGING the release to master (e.g. release/1.5.1 to master) +# +# The script will do the following: +# 1. gradle build (w/o tests) +# 2. create tag and release based on a simple version of CHANGELOG from the current branch HEAD +# 3. upload /dist/app/*.jar to release assets +# 4. upload Archives to OSS Sonatype Central (you must fill in signing info in gradle.properties with private key file) +# +# Note: Release note is NOT changelog. We strongly suggest to manually write up changelog instead of using gitchangelog as change log. + + +COMMIT=$(git rev-parse HEAD) + +REPO="$1" +shift + +TAG="$1" +shift + +TOKEN="$1" +shift + +LASTTAG="$1" +shift + +rm -rf CHANGELOG_simple.md +gitchangelog ^"$LASTTAG" HEAD > temp_CHANGELOG.md +# Convert all line breaks to explicit escape +sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' temp_CHANGELOG.md > temp_CHANGELOG_simple.md +rm -rf temp_CHANGELOG.md +# Remove all asterisks and slash +sed 's/\*\+/\\n/g' temp_CHANGELOG_simple.md > temp_CHANGELOG.md +sed 's/-/\\n/g' temp_CHANGELOG.md > CHANGELOG_simple.md +rm -rf temp_CHANGELOG.md +rm -rf temp_CHANGELOG_simple.md +vi CHANGELOG_simple.md + +rm -rf VERSION +touch VERSION +echo "$TAG" > VERSION +sed -i 's/v//g' VERSION + +rm -rf dist/app +gradle build -x test + +.one-button-release/release.sh $REPO $COMMIT $TAG $TOKEN -- dist/app/*.jar < CHANGELOG_simple.md +rm -rf CHANGELOG_simple.md + +# gradle uploadArchives \ No newline at end of file diff --git a/.one-button-release/release.sh b/.one-button-release/release.sh new file mode 100644 index 00000000..c11a1092 --- /dev/null +++ b/.one-button-release/release.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +set -e +[ -z "$DEBUG" ] || set -x; + +usage() { + echo "$0 [-- ] [< ]" >&2; +} + +if [ "$1" = "-h" -o "$1" = "--help" ]; then + usage + cat >&2 <\`: ":user/:name" of the repository. For example, "chaoxinhu/WeIdentity". + * \`\`: Commit hash or HEAD of your branch name. For example, "master". + * \`\`: Name of the tag and the version for this release. For example, "1.7.0". + * \`\`: GitHub token (permissions required for pushing on your repo). + * \`-- \`: Specific standalone assets to be uploaded along with the release. + * \`< \`: Release Notes file (preferably .md). +EXAMPLES: + $ ./release.sh chaoxinhu/WeIdentity v1.5.0 -- dist/app/*.jar + Creates a release named "v1.5.0" and adds any jar file in + \`dist/app/\` as an asset. + $ ./release.sh chaoxinhu/WeIdentity v1.5.1 -- dist/app/*.jar < notes.md + Same as above, but also append the paragraph content in notes.md + as the release notes. +NOTES: +1. The release notes function is still experimental. Use \n when necessary if you +encounter json parsing errors, in your .md file. +2. Generate GitHub token at https://github.com/settings/tokens and make sure +it has access to the \`"repo"\` scope. +EOS + exit 1; +fi + +[ -n "$2" ] || (usage; exit 1); + +REPO="$1" +shift + +COMMIT="$1" +shift + +TAG="$1" +shift + +TOKEN="$1" +shift + +if [ "$1" = "--" -a "$#" -ge "2" ]; then + shift + ASSETS="$@" +fi + +BODY="" +[ -t 0 ] || BODY=`cat`; + +API_JSON=$(printf '{"tag_name": "%s", "target_commitish": "%s", "name": "WeIdentity Java SDK %s Release", "body": "Version %s: %s", "draft": false, "prerelease": false}' $TAG "$COMMIT" $TAG $TAG "$BODY") + +echo "$API_JSON" + +RESP=$(curl --data "$API_JSON" https://api.github.com/repos/$REPO/releases?access_token=$TOKEN) + +echo $RESP + +upload_url="$(echo "$RESP" | jq -r .upload_url | sed -e "s/{?name,label}//")" + +for file in $ASSETS; do + curl --header "Content-Type:application/gzip" \ + -H "Authorization: token $TOKEN" \ + --data-binary "@$file" \ + "$upload_url?name=$(basename "$file")" +done diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1bcb0d9e..00000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -sudo: false -dist: trusty - -language: java -jdk: - - oraclejdk8 - -before_install: - - gradle wrapper - -script: - - chmod +x ci/script/build-ci.sh - - ci/script/build-ci.sh - - travis_wait 30 ./gradlew check - - ./gradlew jacocoTestReport - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/ALLCONTRIBUTOR.md b/ALLCONTRIBUTOR.md new file mode 100644 index 00000000..1946e8b8 --- /dev/null +++ b/ALLCONTRIBUTOR.md @@ -0,0 +1,50 @@ + +[![All Contributors](https://img.shields.io/badge/all_contributors-23-orange.svg?style=flat-square)](#contributors-) + + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

webankadmin

💼

junqizhang

🚧

chenhaozx

🚧

chaoxinhu

🚧

chent57

🚧

darwindu

🚧

杨刚

🚧

anyspa

🚧

chirdxing

💻

hupeng

💻

chenqping

💻

chengzi8705

💻

The-Emperor1

💻

robert

💻

renranshengxia

💻

xinjiandong

💻

eason_ryu

💻

tyGavinZJU

💻

Bing

💻

Lin

💻

QibingLee

💻

Eric Chan

💻

Robin Liu

💻
+ + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cc958101..b8befa1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,302 @@ -### V1.0.0 (2018-10-30) +### V3.1.1 (2023-6-15) +- Features: +1. Add purely functional interfaces that does not rely on any storage and blockchain +2. Upgrade API document +- Bugfixes: +1. Upgrade components with known vulnerabilities + + +### V3.1.0 (2023-4-28) +- Features: +1. Add a way for local databases to deploy WeIdentity without deploying blockchain +- Bugfixes: +1. Upgrade components with known vulnerabilities + +### V3.0.0 (2022-12-15) +- Features: +1. The project was restructured to strip the blockchain-related functions and interfaces from the project, as well as the file transfer and format conversion functions from the project +- Bugfixes: +1. the value of sdk.sm-crypto in fisco.properties adapt to FISCO BCOS 3.0 guomi + +### V1.8.6 (2022-10-14) +- Features: +1. Upgrade the property fields in WeIdDocument to conform to the W3C DID Specification +2. Upgrade the way data is stored and retrieved in the weid-contract +3. Upgrade the interfaces related to WeId and Evidence + +### V1.8.5 (2022-08-16) +- Features: +1. Replace the web3sdk with fisco-bcos-java-sdk +2. Support the OSCCA-approved(SM2/SM3) cryptography algorithm +3. Support the FISCO BCOS 3.0.0 (rc4 version) +4. Upgrade the functionality of WeID-Build-Tools to accommodate the new version of weid-java-sdk + +### V1.7.0 (2021-01-08) +- Features: +1. FISCO BCOS 1.3.x support is fully removed - please use the FISCO BCOS 2.x node version respectively. +2. Evidence and WeIdDocument query performance improved due to support batch type blockchain node data lookup. +3. Authority Issuer can be registered by any WeID while only administrator can recognize. +4. Greatly enhanced WeID-Build-Tools functionalities. +5. Persistence now supports Redis as storage layer. + +### V1.6.3-hotfix-1 (2020-08-26) +- Bugfixes: +1. Use batch block transaction receipts getter to improve evidence performance. + +### V1.6.5 (2020-08-14) +- Features: +1. Significantly improve build speed when use together with build-tools. +2. Support WeID owners to add/revoke public keys and authentications. +3. Allow to use public key ID to verify a CredentialPojo. +4. Authority Issuer now requires to call recognizeAuthorityIssuer() from admin/committee. + +- Bugfixes: +1. Fix a minor issue in manipulating multi-group operations. +2. Fix a minor issue in CNS configurations in multiple org cases. +3. Orders of WeID public keys and authentications are preserved when added/removed. + +### V1.6.4 (2020-06-16) +- Bugfixes: +1. Update all dependencies to mitigate potential security risks. + +### V1.6.3 (2020-06-01) +- Features: +1. Multi-group deployment support to separate Evidence and other smart contracts. +2. Users can choose Evidence processing mode (instant or batch-type). +3. Configurations in DB and properties can now be updated automatically. +4. Signature creation is now unified to use Ethereum type with Base64 encoding (v = 0/1). + +- Bugfixes: +1. All WeID delegate calls now requires admin/committee privilege from private key. +2. BarCode and QR Code types are merged. +3. AMOP Listening now requires to specify topic. +4. LiteCredential's Hash and Signature's raw message now correctly includes issuanceDate. +5. Migrate to GitHub Actions for CI and pipeline. + +### V1.6.2 (2020-05-07) +- Features: +1. CryptoService, built-in support for ECIES and RSA encryption and decryption. +2. Support delegate creation and modification of WeID. +3. Lite Credential support, a light-weight portable format which uses Secp256k1 universal signature. +4. Support Offline verification of Credential. +5. Allow customize public key types for WeID e.g. RSA public keys. + +- Bugfixes: +1. Fix a DB Connection Pool initialization issue. +2. Fix a hash conflict issue in offline Evidence transactions. +3. Allow long blockchain operations correctly timed-out. +4. Fix an issue where credential's hash generation contains escape characters in inner Claim json. + +### V1.6.1 (2020-04-12) +- Features: +1. QRCode transportation supports AMOP channel. +2. Evidence supports offline, delayed and timed/cron-job manner blockchain transactions. +3. Evidence supports batch creation transactions. +4. Visualized build-tools now supports batch evidence transactions display and management. + +- Bugfixes: +1. Fix a data inconsistency issue when using AMOP channel in multi-active scenarios. + +### V1.6.0 (2020-03-24) +- Features: +1. Endpoint service now supports reentrance and whitelist for remote servers. +2. Extra values in Evidence is now as log append-only style. The R/W efficiency of Evidence is also improved. +3. Data authorization scheme based on Endpoint service. +4. A new WeIdAuth module to support build of authenticated trusted channel between communicating parties. +5. Transportation module now supports Bar Codes and is refactored. +6. WeIdentity smart contracts deployment now supports CNS management. +7. A new Transmission module to support Cross-process Remote Method Invocation. + +### V1.5.2 (2020-02-24) +- Features: +1. PDF Transportation now forbids content tampering during transportation. +2. Evidence now returns evidence hash instead of address (see API doc for details). +3. Evidence creation and query efficiency is greatly improved. + + +### V1.5.1 (2020-01-22) +- Features: +1. Queried CPT can be cached to local machine (require MySQL setup). +2. New interface generateHash(), accepting File, Credential and String as hashable input. + +- Bugfixes: +1. Multiple miscellaneous bugfixes and development experience enhancements. + +### V1.5.0 (2019-12-30) +- Features: +1. CredentialPojo support Zero-Knowledge-Proof based disclosure. +2. Trusted Timestamp creation based on any non-selectively-disclosed CredentialPojo. + +- Bugfixes: +1. Fix multiple security risk issues from dependencies. +2. Fix multiple JDK version incompatibility issues. + + +### V1.4.2 (2019-12-10) +- Features: +1. Allow WeID owners to remove unused public keys and authentications in WeID Document. +2. Embedded CredentialPojo now supports change disclosure policy of inner CredentialPojo. +3. WeIdentity now supports deployment on different FISCO-BCOS Groups (check docs for details). + +- Bugfixes: +1. Fix various issues when serializing Embedded CredentialPojo. +2. Bump jackson, jacoco and jmockit for security concerns. +3. WeIdentity can now work with JDK1.8+ up to openjdk13. +4. Fix broken Document URLs and simplify the document repository structure. + +### V1.4.1 (2019-11-01) +- Bugfixes: +1. Fixed multiple potential leaks which might cause NPE. +2. Change default deposit signature algorithm when creating PDF to keccak256. +3. Fixed multiple invalid URL links in documentation. +4. Bump lombok to 1.18.10 to be compatible for OpenJDK11. + +### V1.4.0 (2019-09-30) +- Features: +1. Supports PDF creation and transportation from CredentialPojo and Presentation. +2. Credential, CredentialPojo and CredentialWrapper now supports Evidence. +3. Credential supports multi-sign +4. Evidence supports multi-sign +5. Empty Evidence can be created with hash value appended separately. +6. Add an reference implementation of Endpoint Service (used w/ Rest Service). +7. Travis CI pipeline now resides on FISCO-BCOS 2.0. +8. Add an information collection command line tool. +9. Support data timeout in domain storage. + +- Bugfixes: +1. Re-Selectively disclose a selectively disclosed Credential is disallowed. +2. Evidence Info fetched from getEvidence() now uses WeID instead of plain address. +3. Credential and CredentialPojo dates are now in second format. +4. Cipher suites are now unified in Secp256k1. +5. Fix miscellenous errors in sequence diagrams. + +### v1.3.2 (2019-08-16) +- Features: +1. weid-java-sdk supports ci pipeline. +2. Add Command line tool to check AMOP health and WeID existence. +3. Persistence layer supports domain configuration. +4. Support expiration period for Presentation encryption key (24 hrs by default). +5. Transportation now supports Specify(), to allow only eligible WeIDs to access. +6. Add sequence diagrams to all new interfaces in WeID-Java-SDK API document. + +- Bugfixes: +1. Credential Verification now requires CPT format checks. +2. Enhances the parameter validity check in all modules. + + +### v1.3.0 (2019-06-28) +- Features: +1. Official support for FISCO-BCOS 1.3 and 2.0 blockchain nodes and smart contracts by extracting a proxy layer. +2. Combine weidentity.properties and fisco.properties. +3. Support Gradle 5.x, offline compilation for weid-java-sdk and build-tools (docs attached). +4. Credential issuance date can be customized. +5. Credential adds a new interface to extract disclosed claim data directly. + +- Bugfixes: +1. Fixed a bug where dates are not consistent after transfer by fromJson() and toJson(). +2. Project renamed from weidentity-java-sdk to weid-java-sdk. +3. Credential Claim structure now requires "weid" as an obligatory attribute. +4. Added multiple unit test. + +### v1.2.1 (2019-06-19) + +- Features: +1. Remove spring dependencies in weid-java-sdk. +2. Optimize weidentity.properties and fisco.properties files. +3. Incorporate new random salt generator. +4. Support connection pool for persistence layer. +5. Modify docs. + +- Bugfixes: +1. Fixed issue of printing exception log. + +### v1.2.0 (2019-06-06) + +- Features: +1. Add AMOP function to support communication between organizations by blockchain nodes. +2. Modify CreateWeId method to support automatically add public key to user's weidentity did document. +3. Add presentation support. +4. Support of generating QR code. +5. Support creating credential by POJO. + +- Bugfixes: +1. Fixed issue of error result of parsing two event log in one trasaction. + +### v1.1.2 (2019-05-22) + +- Features: +1. ResponseData now contains blockchain transaction information + +- Bugfixes: +1. CreateEvidence should use input DID instead of default private key for authentication +2. WeIdentity Contract dependency now targets to specific instead of latest versions + +### v1.1.1 (2019-03-29) + +- Features: +1. Add adaption of new changes in RestAPI service. +2. Modify @context field and add Credential Serilization interface +3. Add Evidence support in Build-tools +4. Add fundamental support of storage connectivity layer + +- Bugfixes: +1. Fixed the query error in Multithread Synchronized Block Output +2. Fixed numerous image and URL errors in SDK documentation. +3. Multiple Code Quality improvements + +### v1.1.0 (2019-01-31) + +- Features: +1. The first version implementation of selective disclosure. +2. The first version implementation of evidence. +3. Download weidentity-contract.jar from maven instead of local. +4. Use JSON string as parameter in class cptServiceImpl and credentialServiceImpl instead of plain string. + +- Documents modifications: +1. Move SDK document from WeIdentity project to this project. +2. Use embedded mermaidjs plugin to render sequences diagram instead of PNG files. + +### v1.0.3 (2018-12-20) + +* Features: +1. Add cache rules in travis-ci config. Only apply CI build on master, develop and tag. +2. Auto release when add a new tag. +3. Minor issues fix in gradle build configuration. + +* Bugfixes: +1. Fix issues found by code safe scan. +2. Fix issues found by checkstyle and spotbugs. + +### v1.0.2 (2018-12-14) + +* Features: +1. Remove codecov patch check +2. Modify FISCO-BCOS sdk ca.crt and client.keystore file +3. Use correct badge url from WeBankFinTech + +* Bugfixes: +1. Fix issues found by codacy. + +### v1.0.1 (2018-11-30) + +* 新增功能: +1. 增加了对Travis CI(travis-ci.org), Maven中央仓库, 代码质量检测(codefactor.io & codacy.com), 代码覆盖率检测(codecov.io)等工具的集成。 +2. 增加了完整的Demo及单元测试的集成。 + +* 问题修复: +1. 修复了大量代码格式问题及输入参数错误问题。 + +* Features: +1. Added Travis CI (travis-ci.org), Maven central repository, code quality tools (codefactor.io & codacy.com), and code coverage tools (codecov.io) integration. +2. Added extensive Demo and Unit Test integration. + +* Bugfixes: +1. Miscellenous code style and input parameter validation issues are fixed. + +### v1.0.0 (2018-10-30) 首次release. -* 新增: +* 新增功能: 1. WeIdService相关接口及实现 2. AuthorityIssuerService相关接口及实现 3. CptService相关接口及实现 @@ -9,11 +304,12 @@ 5. 支持FISCO-BCOS相关操作接口,包括合约部署、调用,支持通过配置私钥方式进行FISCO-BCOS合约调用 6. 支持一键快速部署 -first release for weidentity-java-sdk, with the core features of WeIdentity Spec. +First release for weidentity-java-sdk, with the core features of WeIdentity Spec. -1.WeIdentityService Interface and corresponding implementation. -2.AuthorityIssuerService Interface and corresponding implementation. -3.CptService Interface and corresponding implementation. -4.CredentialService Interface and corresponding implementation. -5.Support set the whole environment upon FISCO-BCOS, including contract deploying, contract function call. -6.Provide a hassle-free installation tools for quick environment setup. +* Features: +1. WeIdentityService Interface and corresponding implementation. +2. AuthorityIssuerService Interface and corresponding implementation. +3. CptService Interface and corresponding implementation. +4. CredentialService Interface and corresponding implementation. +5. Support set the whole environment upon FISCO-BCOS, including contract deploying, contract function call. +6. Provide a hassle-free installation tools for quick environment setup. diff --git a/COPYING b/COPYING deleted file mode 100644 index f288702d..00000000 --- a/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/COPYING.LESSER b/COPYING.LESSER deleted file mode 100644 index 0a041280..00000000 --- a/COPYING.LESSER +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README-en.rst b/README-en.rst new file mode 100644 index 00000000..b17032e3 --- /dev/null +++ b/README-en.rst @@ -0,0 +1,139 @@ +`中文版本 <./README.rst>`_ | English Version + +.. image:: context/weidentity-logo.png + :target: context/weidentity-logo.png + +---- + +What is WeIdentity? +=================== + +WeIdentity is a blockchain solution on Open Consortium Chain to serve as a hub for identity authentication by establishing identity of entities (e.g. persons or objects) on the chain and allowing the interchange of such information among organizations when authorized. +WeIdentity is an open source platform built by WeBank and promotes the values of Open Consortium Chain: streamline resources, collaborate to produce values and serve the public. + +Modules +------- + +WeIdentity includes two major modules: WeIdentity DID and WeIdentity Credential. + +Decentralized Identifiers (WeIdentity DID) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Traditionally, user identity is issued and managed by single centralized organization. With the advent of blockchain technology, it is possible to publish and distribute user identity on chain to allow more than one organization to manage on as a multi-centers solution +WeIdentity DID Module has come with a distributed identification protocol based on \ `FISCO-BCOS Blockchain Platform `_\ , and \ `W3C DID specification `_\, to create identities on chain and associate it with any person or object in the real world. Moreover, DID ensures the Subject’s owner with full rights of control and ownership of the identities. + +The design goals of WeIdentity DID: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ObjectiveDescription
DistributedDistributed ID registration model removes the dependencies on traditional single, centralized registration organization.
Open SourcedThe solution is fully open sourced and publicly available.
PrivacyThe actual content of identity or credential are stored off-chain to maintain minimal information on the chain. Such can prevent any 3rd party from speculating the actual identity in real-world using the information on the chain.
PortabilityData on WeIdentity can be ported into mainstream blockchain platforms or those which are compliant with WeIdentitie’s specification.
InteroperabilityProvides standard interfaces to support cross chains or cross platforms interoperation.
ExtensibilityThe data model can be extended for different business scenarios while maintaining its operability, portability and simplicity.
+
+ + + + +WeIdentity Credential +^^^^^^^^^^^^^^^^^^^^^ + +There are a lot of credentials describing identity in daily life such as personal identity card, driving license, account book, prescription, graduate certificate, property ownership certificate and credit report. WeIdentity Credential offers a complete set of `W3C Verifiable Credentials `_ based solutions designated to standardize and digitize such credentials into a verifiable and interchangeable format. The solution also supports Selectively Disclosure of Credential attributes and generating evidence of Credentials on blockchain. + +WeIdentity encourages certificate organization to issue their own standardized credential templates to enrich the ecosystem on open consortium chain. + +More +^^^^ + +* + `Use Cases and Scenarios (Chinese Version) `_ + +* + `WeIdentity Specification (Chinese Version) `_ + +* + `FAQ `_ + +Current Status +--------------- + +WeIdentity is running on top of FISCO-BCOS with JAVA SDK provided for developers, please review the Installation & Deployment guide and SDK user guide listed below: + + +.. raw:: html + + + + + + + + + + + + + +
Integration MethodDocumentationStatus
JAVA SDK + + + + + + + + + + +
+
+ + +Diving in +---------------- + +Now, please feel free to dive in via \ `this page `_ for a one-stop experience of WeIdentity. + + + +Contributions +--------------- + +You can find all our contributors in \ `this page <./ALLCONTRIBUTOR.md>`_ . Thanks for everything these guys have done for WeIdentity! + + +Contact Us +---------- + +Email:weidentity@webank.com diff --git a/README.md b/README.md deleted file mode 100644 index 5eb9be69..00000000 --- a/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# WeIdentity JAVA SDK - ---- - -## 总体介绍 - -WeIdentity Java SDK提供了一整套对WeIdentity进行管理操作的Java库。 -目前,SDK支持本地密钥管理、数字身份标识(WeIdentity DID)管理、 -标准化凭证(WeIdentity Credential)管理、 -授权机构(Authority Issuer)管理、 -标准化模板(CPT)管理等功能, -同时也提供基于FISCO-BCOS的区块链交互、智能合约的部署与调用。 -未来还将支持更丰富的功能和应用。 - -## 关于 - -* WeIdentity Project对应的合约代码。需配合FISCO-BCOS和weidentity-java-sdk使用,更多详细信息详见: [WeIdentity Project](https://github.com/webankopen/WeIdentity) - -## 联系我们 - -邮箱:weidentity@webank.com - -## License - -This project is released under [LGPLv3](https://opensource.org/licenses/LGPL-3.0). diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..6cec11b8 --- /dev/null +++ b/README.rst @@ -0,0 +1,143 @@ +中文版本 | `English Version <./README-en.rst>`_ + +.. image:: context/weidentity-logo.png + :target: context/weidentity-logo.png + + +---- + +什么是 WeIdentity? +======================== + +WeIdentity是一套分布式多中心的技术解决方案,可承载实体对象(人或者物)的现实身份与链上身份的可信映射、以及实现实体对象之间安全的访问授权与数据交换。WeIdentity由微众银行自主研发并完全开源,秉承公众联盟链整合资源、交换价值、服务公众的理念,致力于成为链接多个垂直行业领域的分布式商业基础设施,促进泛行业、跨机构、跨地域间的身份认证和数据合作。 + +模块介绍 +-------- + +WeIdentity目前主要包含两大模块:WeIdentity DID以及WeIdentity Credential。 + +分布式身份标识 (WeIdentity DID) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +传统方式中,用户的注册和身份管理完全依赖于单一中心的注册机构;随着分布式账本技术(例如区块链)的出现,分布式多中心的身份注册、标识和管理成为可能。 +WeIdentity DID模块在\ `FISCO-BCOS区块链底层平台 `_\ 上实现了一套符合\ `W3C DID规范 `_\ 的分布式多中心的身份标识协议,使实体(人或物)的现实身份实现了链上的身份标识;同时,WeIdentity DID给与Subject(人或者物)直接拥有和控制自己身份ID的能力。 + +WeIdentity DID秉承以下设计理念: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
目标说明
多中心分布式多中心的ID注册机制,摆脱对传统模式下单一中心ID注册的依赖
开源开放技术方案完全开源,面向政府、企业、开发者服务
隐私保护实体的现实身份和可验证数字凭证的内容进行链下存储。支持实体将信息最小化或者选择性披露给其他机构,同时防止任何第三方反向推测出实体在现实世界或其他场景语义中的身份
可移植性基于WeIdentity规范,数据可移植至遵循同样规范的其他平台,兼容业务主流区块链底层平台
互操作性提供标准化接口,支持跨链、跨平台互操作
可扩展性保证操作性,可移植性或简单性的情况下,数据模型可以通过多种不同方式进行扩展
+
+ + + + +可验证数字凭证 (WeIdentity Credential) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +现实世界中存在着各种各样用于描述实体身份、实体间关系的数据,如身份证、行驶证、存款证明、处方、毕业证、房产证、信用报告等。WeIdentity Credential提供了一整套基于\ `W3C VC规范 `_\ 的解决方案,旨在对这一类数据进行标准化、电子化,生成可验证、可交换的「凭证」(Credential),支持对凭证的属性进行选择性披露,及生成链上存证(Evidence)。 + +WeIdentity支持认证机构自行注册标准化凭证模板,共同丰富公众联盟链的生态。 + +更多 +^^^^ + +* + `案例及场景 `_ + +* + `WeIdentity规范文档 `_ + +* + `WeIdentity及其组件的兼容版本说明文档 `_ + + +当前状态 +-------- + +WeIdentity目前支持基于FISCO-BCOS的区块链,并提供Java SDK及RestService方式供部署。具体的规范文档、安装部署和使用指引如下表所示: + + +.. raw:: html + + + + + + + + + + + + + +
集成方法文档入口当前状态
Java SDK + + + + + + + + + + +
+
+ + +感受WeIdentity +---------------- + +接下来,您可以在\ `此页 `_,一站式了解WeIdentity的参考场景,体验Demo流程,并了解完整的部署方式及参考实现。 + + +联系我们 +-------- + +邮箱:weidentity@webank.com + + +如何贡献 +-------- + +* 我们所有的贡献者名单页面在 \ `这里 <./ALLCONTRIBUTOR.md>`_ 。感谢大家为WeIdentity付出的心血! + +* + 详见:\ `如何贡献 `_ + diff --git a/Task21.md b/Task21.md new file mode 100644 index 00000000..1925b6a2 --- /dev/null +++ b/Task21.md @@ -0,0 +1,130 @@ +# **Task 21** + +## **任务** + +实现新的密钥或助记词备份机制,比如社交恢复,m of n共享。 + +## **设计** + +### **设计思路** + +使用Shamir's Secret Sharing算法来实现新的密钥或助记词备份机制。 + + + +这个算法可以将一个私钥拆分成多个部分,只有在满足m个部分的情况下才能还原出原始的私钥。例如,在社交恢复中,可以将私钥拆分成n份并分发给不同的好友,只有当有m个好友汇聚在一起时才能重新拥有这个私钥。 + + + +### **代码** + +以下是用Go语言实现Shamir's Secret Sharing算法的代码示例: + + + +``` +package main + +import ( + "crypto/rand" + "fmt" + "math/big" +) + +type Point struct { + x, y *big.Int +} + +func (p1 Point) add(p2 Point) Point { + return Point{new(big.Int).Add(p1.x, p2.x), new(big.Int).Add(p1.y, p2.y)} +} + +func (p1 Point) mul(m *big.Int) Point { + return Point{new(big.Int).Mul(p1.x, m), new(big.Int).Mul(p1.y, m)} +} + +func evalPoly(poly []*big.Int, x *big.Int) *big.Int { + res := big.NewInt(0) + tmp := big.NewInt(1) + for _, coef := range poly { + res.Add(res, tmp.Mul(coef, tmp)) + tmp.Mul(tmp, x) + } + return res +} + +func splitSecret(secret *big.Int, m, n int) ([]Point, error) { + if m > n { + return nil, fmt.Errorf("m should be less than or equal to n") + } + + poly := make([]*big.Int, m) + poly[0] = secret + for i := 1; i < m; i++ { + coef, err := rand.Int(rand.Reader, big.NewInt(256)) + if err != nil { + return nil, fmt.Errorf("failed to generate random coefficient: %v", err) + } + poly[i] = coef + } + + points := make([]Point, n) + for i := 1; i <= n; i++ { + x := big.NewInt(int64(i)) + y := evalPoly(poly, x) + points[i-1] = Point{x, y} + } + return points, nil +} + +func recoverSecret(points []Point) (*big.Int, error) { + if len(points) == 0 { + return nil, fmt.Errorf("points should not be empty") + } + + var secret *big.Int + for i, p1 := range points { + numerator := big.NewInt(1) + denominator := big.NewInt(1) + for j, p2 := range points { + if i == j { + continue + } + numerator.Mul(numerator, p2.x) + diff := new(big.Int).Sub(p2.x, p1.x) + denominator.Mul(denominator, diff) + } + tmp := new(big.Int).Div(numerator, denominator) + tmp.Mul(tmp, p1.y) + if secret == nil { + secret = tmp + } else { + secret.Add(secret, tmp) + } + } + return secret, nil +} + +func main() { + // Example usage: + secret := big.NewInt(20230520) + m, n := 3, 5 + points, err := splitSecret(secret, m, n) + if err != nil { + fmt.Printf("failed to split secret: %v", err) + return + } + fmt.Println("Points:") + for _, p := range points { + fmt.Printf("(%v, %v)\n", p.x, p.y) + } + + recoveredSecret, err := recoverSecret(points[:m]) + if err != nil { + fmt.Printf("failed to recover secret: %v", err) + return + } + fmt.Println("Recovered secret:", recoveredSecret) +} +``` + diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..f3fcca98 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.1.1-rc.1 \ No newline at end of file diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/.DS_Store" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/.DS_Store" new file mode 100644 index 00000000..fa42c0b6 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/.DS_Store" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\346\265\201\347\250\213\344\275\223\351\252\214.md" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\346\265\201\347\250\213\344\275\223\351\252\214.md" new file mode 100644 index 00000000..77cc14d2 --- /dev/null +++ "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\346\265\201\347\250\213\344\275\223\351\252\214.md" @@ -0,0 +1,88 @@ +// 鹏 WeIdentity 自定义任务 40 + +**教程 之 WeIdentity 入门:学习图谱和体验流程 + +— 附件1:搭建 WeIdentity 所需的 “ 单链 2 机构 2 群组 2 节点 ” + +— 附件2:使用 WeIdentity 部署工具:weid-build-tools,完成部署( 可视化 ) + +— 附件3:WeIdentity Restful API - postman + + + +# WeIdentity 入门:学习图谱和流程体验 + +基于区块链技术的分布式数字身份,是一种自我主权、可验证的新型数字身份。W3C 为这种数字身份定义了: + +​ ① **分布式数字身份标识符** Decentralized Identifiers( Ξ [DIDs](https://w3c.github.io/did-core/) ):Core architecture, data model, and representations + +​ ⇓ ± ② **可验证数字凭证 VC 规范**:Ξ [Verifiable Credentials Data Model v2.0](https://w3c.github.io/vc-data-model/) + +​ Ξ △ [WeIdentity 规范](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-spec.html) 提供了对 W3C DIDs 和 VC 规范的完整实现,并提供了丰富的周边支撑工具和服务 + +WeIdentity-1 + + + +## WeIdentity 的部署和使用:使用依赖区块链 / ~~不依赖区块链的方式~~ + + + +**(一)准备工作** + +- **操作系统**:CentOS( 7.2.* 64位 )或 Ubuntu( 16.04 64 位 ),以 CentOS 为例 +- **JDK**:要求 Oracle JDK 1.8+,如果在使用 WeIdentity 过程中,发现 JDK 版本导致的任何问题,推荐使用: + +​ jdk8u141、jdk8u212、jdk8u231;JDK 与 WeID 直接的兼容性,可参考:Ξ [兼容性文档](https://weidentity.readthedocs.io/zh_CN/latest/docs/weid-compatibility-test.html) + +``` +$ java -version + +java version "1.8.0_231" +Java(TM) SE Runtime Environment (build 1.8.0_231-b11) +Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode) +``` + +- **搭建 FISCO-BCOS 区块链环境:** + +​ 以 ⭐️ WeIdentity 所需要的 “ **单链 2 机构 2 群组 2 节点( 见,附件1 )** ” 为例 + +​ ± ⭐️ Ξ [**搭建 WeBase 管理平台:Docker 一键部署**](https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Install/docker_install.html) + +- **网络连通**:检查部署 WeIdentity JAVA SDK 的服务器,是否能 telnet 通 FISCO BCOS 节点的 channel 端口 + + + +------ + + + +**(二)使用 WeIdentity 部署工具:**⭐️ **weid-build-tools**( **可视化方式( 见,附件2 )) / ** Ξ [其他功能](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-quick-tools-web.html) ),**完成部署** + +​ **⇓ ** **部署 ① 智能合约( Ξ [设计与实现](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-contract-design.html) )** ⇑ ↔ ~~也可以使用:Ξ [命令行方式](https://weidentity.readthedocs.io/zh_CN/latest/docs/deploy-via-commandline.html)~~ + +​ **② WeIdentity-Java-SDK** **(** **Ξ [接口文档](https://weidentity.readthedocs.io/projects/javasdk/zh_CN/latest/) )** + + + +​ ↗ ( **方式一**:通过 ~~**JAVA** API 方式调用 SDK~~ ) ↖ 另,Ξ ~~[WeIdentity JAVA SDK 便捷使用工具](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-quick-tools.html)~~ + +​ 运行 Ξ [Sample](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-sample.html) or Ξ [Kit](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-kit.html),体验接口( 示例 ) ↗ + +​ Ξ [~~在自己的 Java Service 中集成 WeIdentity-Java-SDK~~](https://weidentity.readthedocs.io/zh_CN/latest/docs/sdk-integration.html) **⇓⇓** + + + +​ **方式二**:如果使用的是其他语言( ~ ),而 **非 Java**,可以使用 ⭐️ **WeIdentity ③ RestService**( Ξ [文档](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-rest.html) | [GitHub 仓库](https://github.com/WeBankBlockchain/WeIdentity-Rest-Service) ) + +​ — 即:WeIdentity Restful HTTP Service,提供了简化的 WeIdentity 集成方式与访问能力 + +​ 「 Ξ [部署](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-rest-deploy.html) 」使用者仅需将 RestService 部署到一台 JAVA 的机器上 + +「 **使用**:Ξ [API 接口](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-rest-api.html)( Postman,见附件3 ) ⇓⇓⇓ ⭐️ ④ ~ 中间层 」就可以使用各类 HTTP/HTTPS 协议访问 WeIdentity 的功能了 ... + + + +## 应用:基于 WeIdentity ~ 中间层 的 ⭐️ XXX( 略 ) + +( 略 ) \ No newline at end of file diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/1.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/1.png" new file mode 100644 index 00000000..53a51c3b Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/1.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/10.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/10.png" new file mode 100644 index 00000000..5998c057 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/10.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/11.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/11.png" new file mode 100644 index 00000000..ff1d4866 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/11.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/12.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/12.png" new file mode 100644 index 00000000..5ba25acc Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/12.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/13.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/13.png" new file mode 100644 index 00000000..cfc005d6 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/13.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/14.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/14.png" new file mode 100644 index 00000000..7bd9fdd3 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/14.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/15.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/15.png" new file mode 100644 index 00000000..049e0480 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/15.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/16.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/16.png" new file mode 100644 index 00000000..a47072b1 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/16.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/17.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/17.png" new file mode 100644 index 00000000..02f35a32 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/17.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/18.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/18.png" new file mode 100644 index 00000000..1da9adad Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/18.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/19.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/19.png" new file mode 100644 index 00000000..ffaa14a4 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/19.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/2.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/2.png" new file mode 100644 index 00000000..3a6c6049 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/2.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/20.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/20.png" new file mode 100644 index 00000000..ff605840 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/20.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/21.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/21.png" new file mode 100644 index 00000000..ec85c0bd Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/21.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/22.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/22.png" new file mode 100644 index 00000000..2e833a8d Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/22.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/3.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/3.png" new file mode 100644 index 00000000..daf3712b Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/3.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/4.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/4.png" new file mode 100644 index 00000000..2aa4260a Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/4.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/5.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/5.png" new file mode 100644 index 00000000..f3451932 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/5.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/6.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/6.png" new file mode 100644 index 00000000..4c36524a Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/6.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/7.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/7.png" new file mode 100644 index 00000000..bd6368b2 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/7.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/8.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/8.png" new file mode 100644 index 00000000..92509ee7 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/8.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/9.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/9.png" new file mode 100644 index 00000000..1202d252 Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/9.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/WeIdentity-1.png" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/WeIdentity-1.png" new file mode 100644 index 00000000..cd09a05f Binary files /dev/null and "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/img/WeIdentity-1.png" differ diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2661\357\274\232\346\220\255\345\273\272 WeIdentity \346\211\200\351\234\200\347\232\204 \342\200\234 \345\215\225\351\223\276 2 \346\234\272\346\236\204 2 \347\276\244\347\273\204 2 \350\212\202\347\202\271 \342\200\235.md" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2661\357\274\232\346\220\255\345\273\272 WeIdentity \346\211\200\351\234\200\347\232\204 \342\200\234 \345\215\225\351\223\276 2 \346\234\272\346\236\204 2 \347\276\244\347\273\204 2 \350\212\202\347\202\271 \342\200\235.md" new file mode 100644 index 00000000..7056c435 --- /dev/null +++ "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2661\357\274\232\346\220\255\345\273\272 WeIdentity \346\211\200\351\234\200\347\232\204 \342\200\234 \345\215\225\351\223\276 2 \346\234\272\346\236\204 2 \347\276\244\347\273\204 2 \350\212\202\347\202\271 \342\200\235.md" @@ -0,0 +1,82 @@ +## 搭建 WeIdentity 所需的 “ 单链 2 机构 2 群组 2 节点 ” + + + +``` +// 开发部署工具 build——chain.sh 脚本,依赖于 openssl、curl,请根据所在操作系统,安装依赖 + +sudo yum install -y openssl openssl-devel // 以 centos 为例 +``` + + + +#### 1. 创建操作目录,下载开发部署工具 build_chain.sh 脚本 + +``` +# 创建操作目录 +cd ~ && mkdir -p fisco && cd fisco + +# 下载脚本 +curl -#LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.9.1/build_chain.sh && chmod u+x build_chain.sh + +如果因为网络问题导致长时间无法下载build_chain.sh脚本,请尝试: +curl -#LO https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/FISCO-BCOS/FISCO-BCOS/releases/v2.9.1/build_chain.sh && chmod u+x build_chain.sh +``` + +![1](img/1.png) + + + +#### 2. 在 build_chain.sh 同一目录下,创建 ipconf 文件 + +``` +$ vim ipconf + +# 空格分隔的参数分别表示如下含义: +# ip:num: 物理机IP以及物理机上的节点数目 +# agency_name: 机构名称 +# group_list: 节点所属的群组列表,不同群组以逗号分隔 +127.0.0.1 webank 1,2 +127.0.0.1 lcago 1 +``` + + + +#### 3. 一键建链 + +``` +# 根据配置生成区块链,需要保证机器的30300~30301,20200~20201,8545~8546端口没有被占用 + +$ bash build_chain.sh -f ipconf -p 30300,20200,8545 +``` + +![2](img/2.png) + + + +#### 4. 启动节点:节点提供 start_all.sh 和 stop_all.sh 脚本,启动和停止节点 + +``` +# 进入节点目录 +$ cd ~/fisco/nodes/127.0.0.1 + +# 启动节点 +$ bash start_all.sh + +# 停止节点 +$ bash stop_all.sh +``` + +![3](img/3.png) + + + +#### 5. 查看共识是否成功 + +``` +// 主要通过日志中的 +++ 来看是否成功,只有共识成功了,才能算区块链网络搭建好了 + +tail -f nodes/127.0.0.1/node0/log/log* | grep +++ +``` + +![4](img/4.png) \ No newline at end of file diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2662\357\274\232\344\275\277\347\224\250 WeIdentity \351\203\250\347\275\262\345\267\245\345\205\267\357\274\232weid-build-tools\357\274\214\345\256\214\346\210\220\351\203\250\347\275\262\357\274\210 \345\217\257\350\247\206\345\214\226 \357\274\211.md" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2662\357\274\232\344\275\277\347\224\250 WeIdentity \351\203\250\347\275\262\345\267\245\345\205\267\357\274\232weid-build-tools\357\274\214\345\256\214\346\210\220\351\203\250\347\275\262\357\274\210 \345\217\257\350\247\206\345\214\226 \357\274\211.md" new file mode 100644 index 00000000..f2320de0 --- /dev/null +++ "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2662\357\274\232\344\275\277\347\224\250 WeIdentity \351\203\250\347\275\262\345\267\245\345\205\267\357\274\232weid-build-tools\357\274\214\345\256\214\346\210\220\351\203\250\347\275\262\357\274\210 \345\217\257\350\247\206\345\214\226 \357\274\211.md" @@ -0,0 +1,118 @@ +## 使用 WeIdentity 部署工具:weid-build-tools,完成部署( 可视化 ) + + + +#### 1. 安装 WeIdentity 部署工具:weid-build-tools + + + +**「 Ξ [安装 weid-build-tools](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-installation-by-web.html) 」**一个网页工具,可以用来完成 WeIdentity 的部署,同时,也提供了一些其他功能 + +``` +// 这里主要是针对依赖区块链的部署方式 +// 不依赖区块链的 WeIdentity 版本( 3.1.0-rc及以上 ),无需经过可视化部署 + +// 建议在内网环境搭建安装部署 + +// 启动的可视化安装工具,默认会监听 6021 端口,不能对外网开发访问 + +# 下载安装脚本 +wget -c https://gitee.com/WeBank/WeIdentity-Build-Tools/raw/master/common/script/install/weid_install.sh + +# 执行安装脚本:默认使用最新版本的可视化部署工具,如果想安装指定版本,可以使用 -v,如:./weid_install.sh -v 1.0.12 +chmod u+x weid_install.sh +./weid_install.sh +cd weid-build-tools && mkdir -p resources/conf/amop && cp common/script/consumer_p* resources/conf/amop/ + +# 启动 Web 服务,成功后,可以通过 http://IP:6021 访问可视化部署工具的 Web 页面 +./start.sh + +# Then,可以进行 WeIdentity 的部署和其他配置了 ...( 如下所示: ) +``` + +![5](img/5.png) + + + +#### 2. 可视化部署 + +​ 「 Ξ [**使用可视化部署方式,进行部署**](https://weidentity.readthedocs.io/zh_CN/latest/docs/deploy-via-web.html) 」 + +**[1] WeBase 管理平台** + +![6](img/6.png) + + + +**[2] WeIdentity( 可视化 )部署工具** + + + +使用 “ WeIdentity( 可视化 )部署工具 ” 的服务器的 IP,访问 Web 页面:http://IP:6021 + +``` +// 因为 “ WeIdentity 可视化部署工具 ” 没有账号登录机制,所以,必须确保整个环境只在内网可以访问 +// 也就是说,公网的其他用户,不能访问 +``` + + + +**(1)选择集成方式** + +![7](img/7.png) + + + +**(2)选择角色** + +![8](img/8.png) + + + +**(3)配置区块链节点** + +![9](img/9.png) + +![10](img/10.png) + + + +**(4)设置主群组** + +![11](img/11.png) + +![12](img/12.png) + + + +**(5)配置数据库( 可选 )** + +// 准备好数据库 + +![13](img/13.png) + +![14](img/14.png) + +![15](img/15.png) + + + +**(6)创建管理员的 WeID** + +![16](img/16.png) + +![17](img/17.png) + +![18](img/18.png) + +![19](img/19.png) + + + +**(7)部署 WeIdentity 智能合约** + +![20](img/20.png) + +![21](img/21.png) + +![22](img/22.png) \ No newline at end of file diff --git "a/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2663\357\274\232WeIdentity Restful API - postman/WeIdentity Restful API.postman_collection.json" "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2663\357\274\232WeIdentity Restful API - postman/WeIdentity Restful API.postman_collection.json" new file mode 100644 index 00000000..a2e3f5cd --- /dev/null +++ "b/WeIdentity \350\207\252\345\256\232\344\271\211\344\273\273\345\212\241 40 \346\225\231\347\250\213 \344\271\213 WeIdentity \345\205\245\351\227\250\357\274\232\345\255\246\344\271\240\345\233\276\350\260\261\345\222\214\344\275\223\351\252\214\346\265\201\347\250\213/\351\231\204\344\273\2663\357\274\232WeIdentity Restful API - postman/WeIdentity Restful API.postman_collection.json" @@ -0,0 +1,869 @@ +{ + "info": { + "_postman_id": "03db829f-b094-428f-9ef5-856294f0829e", + "name": "WeIdentity Restful API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "15126157" + }, + "item": [ + { + "name": "WeIdentity RestService API", + "item": [ + { + "name": "1、私钥托管模式", + "item": [ + { + "name": "createWeId 创建 WeIdentity DID( 无参创建方式 )", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionName\":\"createWeId\",\n \"functionArg\":{},\n \"transactionArg\":{},\n \"v\":\"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "基于托管模式的 RestService 不允许通过传入公钥参数的方式创建 WeID,这是因为:这样生成的 WeID 私钥不存在于 RestService 本地,因此无法在后续过程中被调用\n\n如果需要通过传入公钥的方式创建 WeID,请使用基于轻客户方式的接口创建\n\n— 入参:application/json\n\n``` json\n{\n \"functionName\":\"createWeId\", // required\n \"functionArg\":{}, // required\n \"transactionArg\":{}, // required\n \"v\":\"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // WeIdentity DID\n}\n\n```" + }, + "response": [] + }, + { + "name": "getWeIdDocument 获取 WeIdentity DID Document", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"transactionArg\": {},\n \"v\": \"1.0.0\",\n \"functionName\": \"getWeIdDocument\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionName\":\"getWeIdDocument\", // required\n \"functionArg\":{\n \"weId\":\"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\" // WeIdentity DID,与 SDK 直接调用的方式入参要求一致,required\n }, // required\n \"transactionArg\":{}, // no-required,传空\n \"v\":\"1.0.0\" // 版本号\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // WeIdentity DID Document\n \"@context\" : \"https://w3id.org/did/v1\",\n \"id\" : \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"created\" : 1553224394993,\n \"updated\" : 1553224394993,\n \"publicKey\" : [ ],\n \"authentication\" : [ ],\n \"service\" : [ ]\n },\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "registerAuthorityIssuer 创建 AuthorityIssuer", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"name\": \"Administration Office\"\n },\n \"transactionArg\": {\n \t\"invokerWeId\": \"private_key\"\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"registerAuthorityIssuer\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"weid\": \"did:weid:0x1Ae5b88d37327830307ab8da0ec5D8E8692A35D3\", // required,WeIdentity DID,与 SDK 直接调用的方式入参一致\n \"name\": \"Sample College\" // required,机构名\n },\n \"transactionArg\": {\n \"invokerWeId\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // required,用于索引私钥的 WeIdentity DID,服务器端会凭此找到所托管的私钥\n // 注意,如果在这里填入了预先定义在 application.properties 里的暗语,则可确保有足够的权限\n },\n \"functionName\": \"registerAuthorityIssuer\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": True // True/False\n}\n\n```" + }, + "response": [] + }, + { + "name": "queryAuthorityIssuer 查询 AuthorityIssuer", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"transactionArg\": {\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"queryAuthorityIssuer\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:\n\n``` json\n{\n \"functionArg\": { // required\n \"weId\": \"did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3\" // required,WeIdentity DID,与 SDK 直接调用的方式入参一致\n },\n \"transactionArg\": { // no-required,传空\n },\n \"functionName\": \"queryAuthorityIssuer\", // required\n \"v\": \"1.0.0\" // required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 完整的 Authority Issuer 信息\n \"accValue\": ,\n \"created\": 16845611984115,\n \"name\": \"Sample College\",\n \"weid\": \"did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3\"\n },\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "registerCpt 创建 CPT", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"cptJsonSchema\": {\n \t\"weid\" : \"Delegator WeID\",\n \t\"receiver\": \"Receiver WeID\",\n \t\"content\": \"Authorized content\"\n }\n },\n \"transactionArg\": {\n \t\"invokerWeId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"registerCpt\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:appliation/json\n\n``` json\n{\n \"functionArg\": {\n \"weId\": \"did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3\", // required,CPT 创建者\n \"cptJsonSchema\":{ // required,CPT Json Schema,与 SDK 直接调用的方式入参一致\n // 说明:CPT Json Schema是什么?应该满足什么格式?\n // 答:Json Schema是一种用来定义Json字符串格式的Json字符串,它定义了CPT应包括的字段、属性及规则。\n // WeIdentity 可以接受 http://json-schema.org/draft-04/schema# 所定义第四版及之前版本作为入参。\n \"title\": \"cpt\",\n \"description\": \"this is cpt\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"the name of certificate owner\"\n },\n \"gender\": {\n \"enum\": [\n \"F\",\n \"M\"\n ],\n \"type\": \"string\",\n \"description\": \"the gender of certificate owner\"\n },\n \"age\": {\n \"type\": \"number\",\n \"description\": \"the age of certificate owner\"\n }\n },\n \"required\": [\n \"name\",\n \"age\"\n ]\n }\n },\n \"transactionArg\": {\n \"invokerWeId\": \"did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3\" // required,用于索引私钥的 WeIdentity DID,服务器端会凭此找到所托管的私钥\n },\n \"functionName\": \"registerCpt\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // cptBaseInfo\n \"cptId\": 2000001,\n \"cptVersion\": 1\n },\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "queryCpt 查询 CPT", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"cptId\": 2000000\n },\n \"transactionArg\": {},\n \"v\": \"1.0.0\",\n \"functionName\": \"queryCpt\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": { // required\n \"cptId\": 10 // required,CPT ID,与 SDK 直接调用的方式入参一致\n },\n \"transactionArg\": { // no-required,传空\n },\n \"functionName\": \"queryCpt\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 完整的 CPT 信息\n \"cptBaseInfo\" : {\n \"cptId\" : 10,\n \"cptVersion\" : 1\n },\n \"cptId\" : 10,\n \"cptJsonSchema\" : {\n \"$schema\" : \"http://json-schema.org/draft-04/schema#\",\n \"title\" : \"a CPT schema\",\n \"type\" : \"object\"\n },\n \"cptPublisher\" : \"did:weid:0x104a58c272e8ebde0c29083552ebe78581322908\",\n \"cptSignature\" : \"HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=\",\n \"cptVersion\" : 1,\n \"created\" : 1553503354555,\n \"metaData\" : {\n \"cptPublisher\" : \"did:weid:0x104a58c272e8ebde0c29083552ebe78581322908\",\n \"cptSignature\" : \"HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=\",\n \"created\" : 1553503354555,\n \"updated\" : 0\n },\n \"updated\" : 0\n },\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "createCredential 创建 Credential", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"issuer\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"cptId\": \"2000000\",\n \"expirationDate\": \"2100-04-18T21:12:33Z\",\n \"claim\": {\n \"weid\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"receiver\": \"did:weid:1:0x49eaf51c60ffc8a42a3deb4c32d69b33e37c6f2f\",\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\"\n }\n },\n \"transactionArg\": {\n \t\"invokerWeId\": \"private_key\"\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"createCredential\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n// ?,以 signature 代替私钥\n\n{\n \"functionArg\": { // required\n \"cptId\": 10, // required,CPT ID\n \"issuer\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\", // required,issuer WeIdentity DID\n \"expirationDate\": \"2019-04-18T21:12:33Z\", // required,过期时间(使用UTC格式)\n \"claim\": { // required,claim Json 结构体,与 SDK 直接调用的方式入参一致\n \"name\": \"zhang san\",\n \"gender\": \"F\",\n \"age\": 18\n }\n },\n \"transactionArg\": { // required\n \"invokerWeId\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // required,用于索引私钥的 WeIdentity DID,服务器端户凭此找到所托管的私钥\n },\n \"functionName\": \"createCredential\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 完整的 Credential 信息\n \"@context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\",\n \"claim\": {\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n },\n \"cptId\": 2000156,\n \"expirationDate\": \"2100-04-18T21:12:33Z\",\n \"id\": \"da6fbdbb-b5fa-4fbe-8b0c-8659da2d181b\",\n \"issuanceDate\": \"2020-02-06T22:24:00Z\",\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"proof\": {\n \"created\": \"1580999040000\",\n \"creator\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"signature\": \"G0XzzLY+MqUAo3xXkS3lxVsgFLnTtvdXM24p+G5hSNNMSIa5vAXYXXKl+Y79CO2ho5DIGPPvSs2hvAixmfIJGbw=\",\n \"type\": \"Secp256k1\"\n }\n },\n \"errorCode\": 0, // 错误码,0 表示成功\n \"errorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "verifyCredential 验证 Credential", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"@context\": \"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1\",\n \"claim\": {\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:1:0x49eaf51c60ffc8a42a3deb4c32d69b33e37c6f2f\",\n \"weid\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"cptId\": 2000000,\n \"expirationDate\": \"2100-04-18T21:12:33Z\",\n \"id\": \"e4c149d2-c52c-42ac-a8f5-adc8c2f58406\",\n \"issuanceDate\": \"2023-10-11T15:17:29Z\",\n \"issuer\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"proof\": {\n \"created\": \"1697008649000\",\n \"creator\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"signature\": \"dgnJQXIpMlFyOTUyonSJ+gLMpQxFVPFNSIBCJB1ESvkQxkZYbz/2qF7Njf0ahRFt/Cf0ZLe2jlOvZsJ/6Su1vQE=\",\n \"type\": \"Secp256k1\"\n }\n },\n \"transactionArg\": {\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"verifyCredential\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"@context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\", // context 值\n \"claim\": { // required,claim Json 结构体,与 SDK 直接调用的方式入参一致\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n },\n \"cptId\": 2000156, // required,CPT ID\n \"expirationDate\": \"2100-04-18T21:12:33Z\", // required,过期时间\n \"id\": \"da6fbdbb-b5fa-4fbe-8b0c-8659da2d181b\", // REQUIRED,?uuid,Credential 的 UUID\n \"issuanceDate\": \"2020-02-06T22:24:00Z\", // required,颁发时间\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\", // required,issuer WeIdentity DID\n \"proof\": { // Credential 签名结构体\n \"created\": \"1580999040000\",\n \"creator\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"signature\": \"G0XzzLY+MqUAo3xXkS3lxVsgFLnTtvdXM24p+G5hSNNMSIa5vAXYXXKl+Y79CO2ho5DIGPPvSs2hvAixmfIJGbw=\",\n \"type\": \"Secp256k1\"\n }\n },\n \"transactionArg\": { // no-required,传空\n },\n \"functionName\": \"verifyCredential\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": true, // True/False\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "createCredentialPojo 创建 CredentialPojo", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"issuer\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"cptId\": \"2000000\",\n \"expirationDate\": \"2100-04-18T21:12:33Z\",\n \"claim\": {\n \"weid\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"receiver\": \"did:weid:1:0x49eaf51c60ffc8a42a3deb4c32d69b33e37c6f2f\",\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\"\n }\n },\n \"transactionArg\": {\n \t\"invokerWeId\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"createCredentialPojo\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": { // required\n \"cptId\": 10, // required,CPT ID\n \"issuer\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\", // required,issuer WeIdentity DID\n \"expirationDate\": \"2019-04-18T21:12:33Z\", // 过期时间(使用UTC格式)\n \"claim\": { // claim Json 结构体,与 SDK 直接调用的方式入参一致\n \"name\": \"zhang san\",\n \"gender\": \"F\",\n \"age\": 18\n }\n },\n \"transactionArg\": { // required\n \"invokerWeId\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // required,用于索引私钥的 WeIdentity DID,服务器端会凭此找到所托管的私钥\n },\n \"functionName\": \"createCredentialPojo\", // required\n \"v\": \"1.0.0\" // required,版本号\n}\n\n// 说明:以 signature 代替私钥\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 完整的 CredentialPojo 信息\n \"cptId\": 2000156,\n \"issuanceDate\": 1580996777,\n \"context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\",\n \"claim\": {\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n },\n \"id\": \"21d10ab1-75fe-4733-9f1d-f0bad71b5922\",\n \"proof\": {\n \"created\": 1580996777,\n \"creator\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0\",\n \"salt\": {\n \"content\": \"ncZ5F\",\n \"receiver\": \"L0c40\",\n \"weid\": \"I4aop\"\n },\n \"signatureValue\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\",\n \"type\": \"Secp256k1\"\n },\n \"type\": [\n \"VerifiableCredential\",\n \"hashTree\"\n ],\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"expirationDate\": 4111737153\n },\n \"errorCode\": 0, // 错误码,0 表示成功\n \"errorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + }, + { + "name": "verifyCredentialPojo 验证 CredentailPojo", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"cptId\": 2000000,\n \"issuanceDate\": 1697008425,\n \"context\": \"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1\",\n \"claim\": {\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:1:0x49eaf51c60ffc8a42a3deb4c32d69b33e37c6f2f\",\n \"weid\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\"\n },\n \"id\": \"9e5f407a-5b05-41e2-bc73-a63d32d1a40d\",\n \"proof\": {\n \"created\": 1697008425,\n \"creator\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"salt\": {\n \"content\": \"MFAvW\",\n \"receiver\": \"tOxfs\",\n \"weid\": \"Kfnju\"\n },\n \"signatureValue\": \"zb1l9gAQ1T7b5K7Fh3DPkiZcBDjO/lqp8KaYC6lGMBBoZhDgrktmPPW7NowWJXN8Le+7BEm96YctW0ZrMEgUxgA=\",\n \"type\": \"Secp256k1\"\n },\n \"type\": [\n \"VerifiableCredential\",\n \"original\"\n ],\n \"issuer\": \"did:weid:1:0x4b750f447c310232ce37f2d5ace6140ef93ff423\",\n \"expirationDate\": 4111737153\n },\n \"transactionArg\": {\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"verifyCredentialPojo\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": { \n \"cptId\": 2000156, // required,CPT ID\n \"issuanceDate\": 1580996777, // required,颁发时间\n \"context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\", // required,context 值\n \"claim\": { // required,claim Json 结构体,与 SDK 直接调用的方式入参要求一致\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n },\n \"id\": \"21d10ab1-75fe-4733-9f1d-f0bad71b5922\", // ? uuid,CredentialPojo 的 UUID\n \"proof\": { // required,Credential 签名值\n \"created\": 1580996777,\n \"creator\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0\",\n \"salt\": {\n \"content\": \"ncZ5F\",\n \"receiver\": \"L0c40\",\n \"weid\": \"I4aop\"\n },\n \"signatureValue\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\",\n \"type\": \"Secp256k1\"\n },\n \"type\": [\n \"VerifiableCredential\",\n \"hashTree\"\n ],\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\", // required,issuer WeIdentity DID\n \"expirationDate\": 4111737153 // required,过期时间\n },\n \"transactionArg\": { // no-required,传空\n },\n \"functionName\": \"verifyCredentialPojo\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": true, // True/False\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\" // 错误信息\n}\n\n```" + }, + "response": [] + } + ], + "description": "总体介绍:\n\n调用接口:POST weid/api/invoke Content-Type: application/json\n\n1. 入参说明\n \n\n每个 API 的入参,都是满足以下格式的 JSON 字符串:\n\n``` json\n{\n \"functionArg\": { // 随调用SDK方法而变的入参 JSON 字符串,具体参数可以查看 SDK 接口文档\n ...\n },\n \"transactionArg\": { // 交易参数 JSON 字符串,仅包括一个变量 InvokerWeId,由传入方决定使用在服务器端托管的具体哪个 WeIdentity DID 所对应的私钥\n \"invokerWeId\":// 用于索引私钥的 WeIdentity DID,服务器端会凭此找到所托管的私钥(非必须,只有在那些需要使用不同身份进行写交易签名的方法( 如,CreateAuthorityIsser )才会需要 )\n },\n \"functionName\":\"\", // 调用的 SDK 方法名,用于决定具体调用 WeIdentity JAVA SDK 的什么功能\n \"v\": \"\" // API 版本号,即调用 API 方法版本\n}\n\n```\n\n2\\. 响应说明\n\n每个 API 的接口返回,都是满足以下格式的 JSON 字符串:\n\n``` json\n{\n \"respBody\":, // 随调用 SDK 方法而变出值 JSON 字符串,即,具体结果随不同的 SDK 调用方法而变 { ... },\n \"ErrorCode\":, // 错误码\n \"ErrorMessage\": // 错误消息,成功时为 \"success\"\n}\n\n```" + }, + { + "name": "2、轻客户端模式", + "item": [ + { + "name": "Encode - CreateWeID 创建 WeIdentity DID( 有参创建方式 )", + "item": [ + { + "name": "第一次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \t\"publicKey\": \"978870416416889679983076739357652892137097344406525666434767708431155392475239591496567952035640408566264627235143888271471053444960378198893918361888848\"\n },\n \"functionName\": \"createWeId\",\n \"transactionArg\": {\n \t\"nonce\": \"14616548136584\"\n },\n \"v\": \"1.0.0\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/encode", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "encode" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"publicKey\": \"712679236821355231513532168231727831978932132185632517152735621683128\" // required,ECDSA 公钥,需要为10进制的整型数字,以字符串形式传入\n },\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\" // required,交易随机数\n },\n \"functionName\": \"createWeId\", // required\n \"v\": \"1.0.0\" // required\n}\n\n```" + }, + "response": [] + }, + { + "name": "第二次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"14616548136584\",\n \"data\": \"0x635ef5a500000000000000000000000084d01b18b47c036e422580ca4043b7beaac8744c000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000d313639373030393935313430380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000016c6469643a776569643a313a307838346430316231386234376330333665343232353830636134303433623762656161633837343463236b6579732d33613131636663372c45643235353139566572696669636174696f6e4b6579323032302c6469643a776569643a313a3078383464303162313862343763303336653432323538306361343034336237626561616338373434632c7a3236726d52453945634d5856584236777a5a5138727a77344e5268566468356744354e6942695651676b467159396335744e63614c633550765271476359436e4774646444557672735a74597548335067796e4c6743415870554e4859766e7742704d51487a7363566a704a68487a6d6247766a55663743715172586a374c323678584b797172597266665934536d785942684b436e6548456842684d5a616a553538394c35576e6a44616d36666136385a72453850694176596e756b375a7434454d7338624451533851673551364a6a73436b4c3700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000786469643a776569643a313a3078383464303162313862343763303336653432323538306361343034336237626561616338373434632330346238643861652c57654964656e746974792c68747470733a2f2f6769746875622e636f6d2f576542616e6b426c6f636b636861696e2f57654964656e746974790000000000000000\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"createWeId\",\n \"v\": \"1.0.0\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/transact", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "transact" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\",\n \"data\": \"809812638256c1235b1231000e000000001231287bacf213c\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"createWeId\",\n \"v\": \"1.0.0\"\n}\n\n```\n\n— 第二次交互,接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // WeIdentity DID\n}\n\n```" + }, + "response": [] + } + ] + }, + { + "name": "Encode - RegisterAuthorityIssuer 创建(注册)Authority Issuer", + "item": [ + { + "name": "第一次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:0x5774e89d8e7fc8ffc1b7fff4b1019a22ac7140fb\",\n \"name\": \"BV-College\"\n },\n \"functionName\": \"registerAuthorityIssuer\",\n \"transactionArg\": {\n \t\"nonce\": \"14616548136584\"\n },\n \"v\": \"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/encode", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "encode" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"name\": \"BV-College\", // required,机构名\n \"weId\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\" // WeIdentity DID,与 SDK 直接调用的方式入参要求一致\n },\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\" // required,交易随机数\n },\n \"functionName\": \"registerAuthorityIssuer\", // required\n \"v\": \"1.0.0\" // required,版本号\n}\n\n```" + }, + "response": [] + }, + { + "name": "第二次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\",\n \"data\": \"809812638256c1235b1231000e000000001231287bacf213c\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"registerAuthorityIssuer\",\n \"v\": \"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/transact", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "transact" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\",\n \"data\": \"809812638256c1235b1231000e000000001231287bacf213c\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"registerAuthorityIssuer\",\n \"v\": \"1.0.0\"\n}\n\n```\n\n第二次交互,接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": { // Authority Isser 信息\n \"accValue\": ,\n \"created\": \"1581420650\",\n \"name\": \"BV-College\",\n \"weId\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n }\n}\n\n```" + }, + "response": [] + } + ] + }, + { + "name": "Encode - RegisterCpt 创建 CPT", + "item": [ + { + "name": "第一次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"weId\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"cptSignature\": \"HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=\",\n \"cptJsonSchema\": {\n \t\"weid\" : \"Delegator WeID\",\n \t\"receiver\": \"Receiver WeID\",\n \t\"content\": \"Authorized content\"\n }\n },\n \"functionName\": \"registerCpt\",\n \"transactionArg\": {\n \t\"nonce\": \"14616548136584\"\n },\n \"v\": \"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/encode", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "encode" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"weId\": \"did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3\", // CPT 创建者\n \"cptJsonSchema\": { // CPT Json Schema,与 SDK 直接调用的方式入参要求一致\n \"title\": \"cpt\",\n \"description\": \"this is cpt\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"the name of certificate owner\"\n },\n \"gender\": {\n \"enum\": [\n \"F\",\n \"M\"\n ],\n \"type\": \"string\",\n \"description\": \"the gender of certificate owner\"\n },\n \"age\": {\n \"type\": \"number\",\n \"description\": \"the age of certificate owner\"\n }\n },\n \"required\": [\n \"name\",\n \"age\"\n ]\n },\n \"cptSignature\": \"BaUeP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\" // 创建者使用自己的私钥对 cptJsonSchema 的签名(与私钥托管方式不同,本方式特有)\n },\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\" // 交易随机数\n },\n \"functionName\": \"registerCpt\", // required\n \"v\": \"1.0.0\" // 版本号,required\n}\n\n```" + }, + "response": [] + }, + { + "name": "第二次交互", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\",\n \"data\": \"809812638256c1235b1231000e000000001231287bacf213c\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"registerAuthorityIssuer\",\n \"v\": \"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/transact", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "transact" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"functionArg\": {},\n \"transactionArg\": {\n \"nonce\": \"1474800601011307365506121304576347479508653499989424346408343855615822146039\",\n \"data\": \"809812638256c1235b1231000e000000001231287bacf213c\",\n \"signedMessage\": \"HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=\"\n },\n \"functionName\": \"registerAuthorityIssuer\",\n \"v\": \"1.0.0\"\n}\n\n```\n\n— 第二次交互,接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": { // Authority Isser 信息\n \"cptId\": 2000001,\n \"cptVersion\": 1\n }\n}\n\n```" + }, + "response": [] + } + ] + }, + { + "name": "Encode - CreateCredentialPojo 创建 CredentialPojo", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"cptId\": \"2000156\",\n \"expirationDate\": \"2100-04-18T21:12:33Z\",\n \"claim\": {\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\"\n }\n },\n \"functionName\": \"createCredentialPojo\",\n \"transactionArg\": {\n },\n \"v\": \"1.0.0\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/encode", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "encode" + ] + }, + "description": "说明:创建 CredentialPojo,不需要进行区块链交互,因此,只需要进行一次 POST weid/api/encode,然后,对返回的结果进行签名即可\n\n— 入参:application/json\n\n``` json\n{\n \"functionArg\": {\n \"cptId\": 10, // CPT ID\n \"issuer\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa\", // issuer WeIdentity DID\n \"expirationDate\": \"2019-04-18T21:12:33Z\", // 过期时间(使用UTC格式)\n \"claim\": { // claim Json 结构体,与 SDK 直接调用的方式入参一致\n \"name\": \"zhang san\",\n \"gender\": \"F\",\n \"age\": 18\n }\n },\n \"transactionArg\": { // no-required,传空\n },\n \"functionName\": \"createCredentialPojo\", // required\n \"v\": \"1.0.0\" // required,版本号\n}\n\n// 说明,以 signature 代替私钥\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 完整的 CredentialPojo 信息\n \"cptId\": 2000156,\n \"issuanceDate\": 1580996777,\n \"context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\",\n \"claim\": {\n \"content\": \"b1016358-cf72-42be-9f4b-a18fca610fca\",\n \"receiver\": \"did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754\",\n \"weid\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\"\n },\n \"id\": \"21d10ab1-75fe-4733-9f1d-f0bad71b5922\",\n \"proof\": {\n \"created\": 1580996777,\n \"creator\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0\",\n \"salt\": {\n \"content\": \"ncZ5F\",\n \"receiver\": \"L0c40\",\n \"weid\": \"I4aop\"\n },\n \"signatureValue\": \"HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=\",\n \"type\": \"Secp256k1\"\n },\n \"type\": [\n \"VerifiableCredential\",\n \"hashTree\"\n ],\n \"issuer\": \"did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa\",\n \"expirationDate\": 4111737153\n },\n \"errorCode\": 0, // 错误码,0 表示成功\n \"errorMessage\": \"success\" // 错误信息\n}\n\n```\n\n**// 需说明的是:**\n\n> 这个生成的CredentialPojo的签名值(proof中的signatureValue项)并没有经过私钥签名。 \n> 正确的签名方式包括下面几步: \n> \\- base64解码,生成一个二进制字节数组 \n> \\- 对解码的byte\\[\\]做一次secp256k1或sm3的hash \n> \\- 对完成hash过byte\\[\\],再做一次hash(如果您使用的是Java web3sdk的SignMessage(),这一步它替您完成了) \n> \\- 传入私钥,进行签名,得到r,s,v - 对进行序列化 \n> \\- 把序列化的byte进行base64编码发回RestService\n\n> 使用ECDSA或SM2私钥进行签名和Base64编码的范例代码见下(Java和Go):\n\n``` java\nRsvSignature signature = DataToolUtils.signToRsvSignature(new String(DataToolUtils.base64Decode(signatureValue)), privateKey);\n\n```\n\n``` go\nbase64SignatureValue := credentialEncodeResponse.RespBody.Proof.SignatureValue\nsignatureValue, err3 := base64.StdEncoding.DecodeString(base64SignatureValue)\nhashedMsg := Hash(signatureValue)\ndoubleHashedMsg := Hash(hashedMsg)\nprivateKeyBytes := ConvertPrivateKeyBigIntToPrivateKeyBytes(privateKeyBigInt)\nsignatureBytes, err4 := SignSignature(doubleHashedMsg, privateKeyBytes)\nsignatureBase64String := base64.StdEncoding.EncodeToString(signatureBytes)\n\n```" + }, + "response": [] + } + ], + "description": "总体介绍:\n\n基于轻客户端模式的 API 的入参方式,与基于私钥托管模式的 API 相同,也是满足以下格式的 JSON 字符串\n\n最大的区别在于,流程包括两次交互:\n\n**「 第一次交互 」**调用接口:POST weid/api/encode Content-Type: application\n\n轻客户端提供接口参数,发送给 RestService 服务端,后者进行组装、编码区块链原始交易串,并返回\n\n1. 接口入参(Body)\n \n\n``` json\n{\n \"functionArg\": { // 随不同的 SDK 方法调用而变的入参json字符串,具体参数可查看 SDK 接口文档\n ...\n },\n \"transactionArg\": { // 交易参数json字符串,required,仅包括一个变量 nonce,用于防止重放攻击的交易随机数\n \"nonce\": // required,用于防止重放攻击的交易随机数,可以使用 RestService Jar 的 getNonce(),或其他类似方法生成此随机数\n // 需说明的是,必须妥善保存,这个 nonce 在第二次交互中还会用到\n }\n \"functionName\":\"\", // 调用的 SDK 方法名,用于决定具体调用 WeIdentity Java SDK 的什么功能\n \"v\": \"\" // 调用的 API 方法版本\n}\n\n```\n\n2\\. 接口返回:application/json\n\n``` json\n{\n \"respBody\": {\n \"blockLimit\": , // 建议使用的交易处理期限,\n \"encodedTransaction\": , // 基于Base64编码的原始交易串信息\n \"data\": // 交易特征值\n }\n \"ErrorCode\": , // 错误码\n \"ErrorMessage\": // 错误信息,成功时为\"success\"\n}\n\n```\n\n→ 返回结构体,包含 encodedTransaction\n\n调用者随后需要使用自己的私钥对 encodeTransaction 进行交易签名,然后,使用 Base64 对其进行编码\n\n→ Then,和 data、nonce 一起待用,进行第二次交互\n\n// 请注意使用的 ECDSA 签名算法的编码格式 - !important\n\n> WeID Java SDK所使用的是椭圆曲线Secp256k1算法,这也是WeID Go轻客户端的默认算法。\n\n> 一般来说,ECDSA的签名算法会生成R,S,V三个值,其中R和S是32个字节的二进制字节数组,而V,以太坊原生的Secp256k1算法的结果一般是0或1;当生成签名的R,S,V之后,需要将R,S,V存入一个65个字节长的二进制字节数组,再进行Base64编码方可正确由RestService解析。\n\n> RestService只接受两种组成方式: 1. 按照R, S, V的顺序拼接成一个65个字节长的数组并使用Base64编码(这是WeID Go轻客户端默认方式) 2. 按照V, R, S的顺序拼接成一个65个字节长的数组并使用Base64编码(这是WeID Java SDK默认序列化方式)\n\n> 可以使用WeID Java SDK代码,使用默认Secp256k1私钥进行签名和Base64编码的范例代码见下(可以在WeID Java SDK的[签名测试用例](https://github.com/WeBankBlockchain/WeIdentity/blob/feature/reconstruction/src/test/java/com/webank/weid/util/TestSignatureUtils.java)里编写和执行下面代码)\n\n``` java\n// 依赖weid-java-sdk 3.1.1-rc.1\nbyte[] decodeTransaction = DataToolUtils.base64Decode(\"\".getBytes());\nString decodeTransactionStr = new String(decodeTransaction);\nRsvSignature signatureResult = DataToolUtils.signToRsvSignature(decodeTransactionStr, privateKey);\nString base64SignedMsg = DataToolUtils.SigBase64Serialization(signatureResult);\n\n```\n\n**「 第二次交互 」**调用接口:POST weid/api/transact Content-Type: application/json\n\n轻客户端在本地使用自己的私钥,对原始交易串进行符合 ECDSA 的 sha3 签名,发给 RestService 服务端,后者打包,并直接执行交易;简单来说就是,将已签名交易的参数发给 RestService,并由后者将交易打包上链\n\n1. 接口入参\n \n\n``` json\n{\n \"functionArg\": { // 传空\n },\n \"transactionArg\": { // 交易参数json字符串\n \"nonce\": , // 用于防止重放攻击的交易随机数,第一次交互起始阶段生成的 nonce\n \"blockLimit\": ,// 用于限制交易处理期限,需和第一步中返回值一致\n \"signType\": , // 签名类型,\"1\"表示RSV,\"2\"表示VRS,如果使用上面WeID Java SDK示例代码来签名,则填\"2\"\n \"data\": , // 交易特征值,需和第一步中返回值一致,即,第一次交互收到的 data\n \"signedMessage\": // 基于Base64编码的、使用私钥签名之后的encodedTransaction签名值,即,第一次交互后,使用者使用本地私钥签名,并通过 base64 编码的 encodedTransaction 的签名值\n },\n \"functionName\": \"\", // 调用的 SDK 方法名,用于决定具体调用 WeIdentity Java SDK 的什么功能\n \"v\": \"\" // 调用的 API 方法版本号\n}\n\n```\n\n2\\. 接口返回:application/json\n\n``` json\n{\n \"respBody\": { // 随调用SDK方法而变的输出值json字符串\n }\n \"ErrorCode\": , // 错误码\n \"ErrorMessage\": , // 错误信息,成功时为\"success\"\n}\n\n```\n\n**// 说明:!important**\n\n基于轻客户端的交易方式,本质上是因为签名操作必须在本地完成,因此,将原始交易串分成了两次交互完成\n\n基于轻客户端的每个 API 的入参,也仅仅在第一次交互中不同,\n\n因此,**该模块的下列 API,会忽略第二次交互的入参,只提供第一次交互的入口和第二次交互的返回值**" + } + ] + }, + { + "name": "WeIdentity Endpoint Service API", + "item": [ + { + "name": "get all endpoint 获取所有已注册的 Endpoint 信息", + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "http://192.168.0.93:7001/weid/api/endpoint", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "endpoint" + ] + }, + "description": "1. 接口入参:无\n2. 接口返回:application/json\n \n\n``` json\n{\n \"ErrorCode\": 0,\n \"ErrorMessage\": \"success\",\n \"respBody\": [\n {\n \"requestName\": \"create-passphrase\",\n \"inAddr\": [\n \"127.0.0.1:6010\",\n \"127.0.0.1:6011\"\n ],\n \"description\": \"Create a valid random passphrase\"\n },\n {\n \"requestName\": \"verify-passphrase\",\n \"inAddr\": [\n \"127.0.0.1:6012\",\n \"127.0.0.1:6013\"\n ],\n \"description\": \"Verify a passphrase\"\n }\n ]\n}\n```" + }, + "response": [] + }, + { + "name": "进行 Endpoint 调用", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"body\": \"abcabc\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/endpoint/duplicate-input", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "endpoint", + "duplicate-input" + ] + }, + "description": "1. 接口入参\n \n\n/{endpont} required,在 API 路径中标明的 API 名,String\n\nbody required,以\\`\\`\\`分隔的多个传入服务端用于执行API的参数\n\n``` json\n{\n \"body\": \"did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa```25\" // required,以```分隔的多个传入服务端用于执行API的参数\n}\n\n```\n\n2\\. 接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": \"did:weid:0x1Ae5b88d37327830307ab8da0ec5D8E8692A35D3\" // SDK 侧的返回值,String\n}\n\n```" + }, + "response": [] + } + ] + }, + { + "name": "WeIdentity 数据授权 API", + "item": [ + { + "name": "Fetch Authorized Data 数据授权 API", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"authToken\": {\n\t \"claim\": {\n\t \"duration\": 360000,\n\t \"fromWeId\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168\",\n\t \"resourceId\": \"4b077c17-9612-42ee-9e36-3a3d46b27e81\",\n\t \"serviceUrl\": \"http://127.0.0.1:6010/fetch-data\",\n\t \"toWeId\": \"did:weid:101:0x68bedb2cbe55b4c8e3473faa63f121c278f6dba9\"\n\t },\n\t \"context\": \"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1\",\n\t \"cptId\": 101,\n\t \"expirationDate\": 1581347039,\n\t \"id\": \"48b75424-9411-4d22-b925-4e730b445a31\",\n\t \"issuanceDate\": 1580987039,\n\t \"issuer\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168\",\n\t \"proof\": {\n\t \"created\": 1580987039,\n\t \"creator\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168#keys-0\",\n\t \"salt\": {\n\t \"duration\": \"fmk5A\",\n\t \"fromWeId\": \"DEvFy\",\n\t \"resourceId\": \"ugVeN\",\n\t \"serviceUrl\": \"nVdeE\",\n\t \"toWeId\": \"93Z1E\"\n\t },\n\t \"signatureValue\": \"HCZwyTzGst87cjCDaUEzPrO8QRlsPvCYXvRTUVBUTDKRSoGDgu4h4HLrMZ+emDacRnmQ/yke38u1jBnilNnCh6c=\",\n\t \"type\": \"Secp256k1\"\n\t },\n\t \"type\": [\"VerifiableCredential\", \"hashTree\"]\n\t},\n\t\"signedNonce\": \"123123\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/authorize/fetch-data", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "authorize", + "fetch-data" + ] + }, + "description": "— 入参:application/json\n\n``` json\n{\n \"authToken\": { // required,CPT101数据授权凭证,需通过DataToolUtils.serialize()方式生成\n \"claim\": {\n \"duration\": 360000,\n \"fromWeId\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168\",\n \"resourceId\": \"4b077c17-9612-42ee-9e36-3a3d46b27e81\",\n \"serviceUrl\": \"http://127.0.0.1:6010/fetch-data\",\n \"toWeId\": \"did:weid:101:0x68bedb2cbe55b4c8e3473faa63f121c278f6dba9\"\n },\n \"context\": \"https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1\",\n \"cptId\": 101,\n \"expirationDate\": 1581347039,\n \"id\": \"48b75424-9411-4d22-b925-4e730b445a31\",\n \"issuanceDate\": 1580987039,\n \"issuer\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168\",\n \"proof\": {\n \"created\": 1580987039,\n \"creator\": \"did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168#keys-0\",\n \"salt\": {\n \"duration\": \"fmk5A\",\n \"fromWeId\": \"DEvFy\",\n \"resourceId\": \"ugVeN\",\n \"serviceUrl\": \"nVdeE\",\n \"toWeId\": \"93Z1E\"\n },\n \"signatureValue\": \"HCZwyTzGst87cjCDaUEzPrO8QRlsPvCYXvRTUVBUTDKRSoGDgu4h4HLrMZ+emDacRnmQ/yke38u1jBnilNnCh6c=\",\n \"type\": \"Secp256k1\"\n },\n \"type\": [\"VerifiableCredential\", \"hashTree\"]\n },\n \"signedNonce\": \"123123\" // required,签名的Nonce值(当前暂不校验,可任意填入)\n}\n\n```\n\n— 接口返回:application/json\n\n``` json\n{\n \"ErrorCode\": 0, // 错误码,0 表示成功\n \"ErrorMessage\": \"success\", // 错误信息\n \"respBody\": \"sample data\", // SDK 侧的返回值,String\n}\n\n```" + }, + "response": [] + } + ] + }, + { + "name": "其他", + "item": [ + { + "name": "Transact - Any", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"functionArg\": {},\r\n \"functionName\": \"createWeId\", \r\n \"transactionArg\": {\r\n \t\"nonce\": \"2678903918699407695\",\r\n \t\"blockLimit\": \"44872\",\r\n \t\"signType\": \"2\",\r\n \t\"data\": \"0x6bf30a0d000000000000000000000000dc99f92911dd8f81b0c24ae018a8d7df41eb098400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000005e45380c00000000000000000000000000000000000000000000000000000000000000c5373439373239383339363337343235343130323237353034373732303838313239393936303834323533313730393338363534353032383431303235343437343433303739373039393430393030303736393631393438343638393832393635323134363034353734343434393731303734373130383236313031303937383337323736353737303537393539373337373836393235303137342f307864633939663932393131646438663831623063323461653031386138643764663431656230393834000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a3135383135393436333600000000000000000000000000000000000000000000\",\r\n \t\"signedMessage\": \"drS4u7MOge9eWfDOWWdTHAZlKoHuSdxg9pqvu80agAQMB2KZBl6c/rV84m2r+4VXKACV02xC1WfcjWeLIJ92EwA=\"\r\n },\r\n \"v\": \"1.0.0\"\r\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001//weid/api/transact", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "", + "weid", + "api", + "transact" + ] + } + }, + "response": [] + }, + { + "name": "createEvidence", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"id\": \"31c38f4c-4d12-40fd-92c4-4d9f1dce0135\",\n \"hash\": \"0x6726391a7fa259470c26a2e9c9467ddbb1f1e7108eeb6f279248b70bb91f8205\",\n \"proof\": \"3divzA7mgEv3774UtZRIxjUeQP0IEzMv/FfnRE6RgMjN1lMuyRJNvHF+N8NJjVydRmC9cWffKJjE30W8Vbk+MwA=\",\n \"log\": \"temp\"\n },\n \"transactionArg\": {\n \t\"groupId\": 1\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"createEvidence\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + } + }, + "response": [] + }, + { + "name": "getEvidence", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"functionArg\": {\n \"hashValue\": \"0x6726391a7fa259470c26a2e9c9467ddbb1f1e7108eeb6f279248b70bb91f8205\"\n },\n \"transactionArg\": {\n \t\"groupId\": 1\n },\n \"v\": \"1.0.0\",\n \"functionName\": \"getEvidence\"\n}" + }, + "url": { + "raw": "http://192.168.0.93:7001/weid/api/invoke", + "protocol": "http", + "host": [ + "192", + "168", + "0", + "93" + ], + "port": "7001", + "path": [ + "weid", + "api", + "invoke" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git "a/Weidentity+\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253.md" "b/Weidentity+\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253.md" new file mode 100644 index 00000000..d649620b --- /dev/null +++ "b/Weidentity+\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253.md" @@ -0,0 +1,263 @@ +## 前言 + +### Weidentity + + - 一套分布式多中心的技术解决方案,可承载实体对象(人或者物)的现实身份与链上身份的可信映射、以及实现实体对象之间安全的访问授权与数据交换 + + - 包含的两大模块:**WeIdentity DID**以及**WeIdentity Credential** + + + +### DID + + - 基于区块链技术的分布式数字身份是一种自我主权的、可验证的、新型数字身份 + + - W3C为这种身份定义了 "分布式数字身份标识符规范"(Decentralized ID,DID) + + > 一种新型的全球标识符 + + - 分布式标识符的用途包括以下两个方面 + + 1. 使用标识符来标识 DID 
主体(人员、组织、密钥,服务和其他一般事物)的特定实例 + + 2. 促进实体之
间创建持久加密的专用通道,无需任何中心化注册机制,它们可以用于诸如凭证交
换和认证 + + - 一个实体可
以具有多个 DID,甚至与另一个实体的每个关系可以关联一个或多个DID(成对假名
和一次性标识符)以保护隐私性,身份所有者通过证明拥有与绑定到该 DID的公钥相
关联的私钥来建立 DID 的所有权 + + + +## 数据授权共享案例 + +### 案例背景 + + > 基于 WeIdentity的SDK进行医疗用户信息管理的代码示例 + + + +在医疗领域中,如何保护用户的个人健康信息,并确保其隐私和安全。传统的医疗信息管理方式存在着信息不透明、数据集中存储、隐私泄露等问题。而基于区块链技术的身份认证和数据管理解决方案,如WeIdentity,可以提供分布式、去中心化、加密保护的数据管理方式,增强了用户对其个人健康信息的掌控权和隐私保护 + + + +### 数据结构 + +1. 描述医疗用户信息的 JSON 格式 的 Schema(模式定义),作为通用数据结构使用 + +2. 结构内包含了三个主要部分:基本用户信息(BasicInfo)、健康状态信息(HealthStatus)和医学历史信息(MedicalHistory) + + ```JSON +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Medical User Information", + "title": "User Data", + "type": "object", + "properties": { + "BasicInfo": { + "description": "Basic User Information", + "type": "object", + "items": { + "type": "object", + "properties": { + "name": { + "description": "User Name", + "maxLength": 30, + "type": "string" + }, + "age": { + "description": "User Age", + "type": "integer" + }, + "birth": { + "description": "User Birth", + "type": "string" + }, + "gender": { + "description": "User Gender", + "enum": [ + "MALE", + "FEMALE" + ], + "type": "string" + } + }, + "required": [ + "name", + "age", + "birth", + "gender" + ] + } + }, + "HealthStatus": { + "description": "Health Status Information", + "type": "object", + "properties": { + "height": { + "description": "User Height", + "type": "number" + }, + "weight": { + "description": "User Weight", + "type": "number" + }, + "blood_type": { + "description": "User Blood Type", + "enum": [ + "A", + "B", + "O", + "AB", + "OTHER" + ], + "type": "string" + }, + "blood_pressure": { + "description": "User Blood Pressure", + "type": "string" + } + }, + "required": [ + "height", + "weight", + "blood_type", + "blood_pressure" + ] + }, + "MedicalHistory": { + "description": "Medical History Information", + "type": "array", + "items": { + "type": "object", + "properties": { + "date": { + "description": "Date of the medical event", + "type": "string" + }, + "description": { + "description": "Description of the medical event", + "type": "string" + } + }, + "required": [ + "date", + "description" + ] + } + } + } +} +``` + +1. 结构数据释义: + + - 基本用户信息(BasicInfo) + + - 该部分包含了基本的用户信息:姓名(name)、年龄(age)、生日(birth)和性别(gender)四个属性 + + - name 属性为字符串类型,最大长度为30个字符 +age 属性为整型 +birth 属性为字符串类型 +gender 属性为字符串类型,取值仅为 "MALE" 或 "FEMALE" + + - 健康状态信息(HealthStatus) + + - 该部分包含了用户的身体健康状态信息,包括身高(height)、体重(weight)、血型(blood_type)和血压(blood_pressure)四个属性 + + - height 属性和 weight 属性均为数字类型 + + blood_type属性为字符串类型,取值只能是 "A"、"B"、"O"、"AB" 或 "OTHER"; + + blood_pressure属性为字符串类型 + + - 医疗历史信息(MedicalHistory) + + - 该部分是一个数组类型,包含了多个对象(可随医用诊断次数而增加数据内容),每个对象代表一个医疗事件,包括事件日期(date)和事件描述(description)两个属性 + + - date 属性为字符串类型 + + description 属性为字符串类型 + +1. 该 Schema 指定了每个部分的必选属性,通过标准化和规范化用户数据的描述,可以为用户身份认证和数据授权提供基础,确保用户数据的安全性和一致性 + + + +### 授权设置 + +1. 用户可以使用 WeIdentity 生成自己的 DID,并在DID上建立与数据相关的授权规则。例如,用户可以设置只有特定的医疗应用程序可以访问和更改其健康状态数据,而其他应用程序只能查询这些数据 + +2. 具体示例: + + ```JavaScript +const WeIdentity = require('weidentity-sdk-js'); +const did = 'did:weid:example:WeIdentity DID'; +const basicAuth = {type: 'BasicAuth', nonce: '...'}; +const accessControl = { + "health_status": { + "read": ["did:weid:example:WeIdentity DID"], + "write": ["did:weid:medical_app:MedicalApp"] + } +}; +const accessToken = await WeIdentity.Signer.signRawTransaction({ + "auth": basicAuth, + "data": accessControl +}, did); + +``` + +1. 示例内容的相关定义: + + 2. 通过 `require('weidentity-sdk-js')` 导入 WeIdentity SDK + + 3. 定义了一个 DID 变量,其中包含了一个 WeID 格式的身份标识 + + 4. 定义了一个基本身份验证(BasicAuth)对象(basicAuth),其中包含了身份验证的类型和一个 nonce(用于增加请求的安全性) + + 5. 定义了一个访问控制对象(accessControl),其中包含了一个示例的访问控制规则,规定了对于名为 "HealthStatus" 的资源的读写权限。其中,读权限限制为只允许`did:weid:example:WeIdentity DID`进行访问,写权限限制为只允许`did:weid:medical_app:MedicalApp`医用程序进行访问 + + 6. 通过调用`WeIdentity.Signer.signRawTransaction()`方法,使用指定的身份验证对象(basicAuth)和访问控制对象(accessControl)作为参数,以当前的 DID 进行签名,生成一个访问令牌(accessToken)这个访问令牌可以用于后续的访问控制操作,以便对受限资源进行读写操作 + +7. 在代码中,用户可使用 DID 来定义数据的访问控制规则 + + - 在`accessControl`对象中,`HealthStatus`属性指定了访问控制规则的作用域 + + - `read`和`write`属性分别指定了读和写的DID列表 + + - 用户可以使用`accessToken`将授权规则保存到区块链上 + + + +### 数据访问 + +1. 应用程序可以使用用户授权生成的 accessToken 来访问数据 + +2. 具体示例: + + ```JavaScript +const WeIdentity = require('weidentity-sdk-js'); +const accessToken = '...'; // user's access token +const healthStatus = await WeIdentity.Did.accessControlDecrypt({ + "accessToken": accessToken, + "cipherText": "encrypted health status" +}); +console.log(HealthStatus); +``` + +1. 示例内容的相关定义: + + 2. 通过 `require('weidentity-sdk-js')` 导入了 WeIdentity SDK(同 → 授权设置) + + 3. 定义了一个访问令牌(accessToken)变量,其中包含了用户的访问令牌,用于进行访问控制操作 + + > 该accessToken是通过`WeIdentity.Signer.signRawTransaction()` 方法生成的 + + 1. 调用`WeIdentity.Did.accessControlDecrypt()`方法,将一个包含了加密的健康状态数据的密文(cipherText)作为参数传递给该方法。此方法会使用指定的访问令牌(accessToken)进行解密操作,并返回解密后的健康状态数据(HealthStatus) + +2. 通过使用访问令牌对加密数据进行解密,在满足访问控制规则的前提下,获取到健康状态数据的明文内容,从而进行后续的医用业务处理 + + + +### 小述 + +- 定义通用数据结构,其包含用户相关医学信息,通过标准化和规范化用户数据的描述,确保用户信息的安全性、可靠性、一致性 + +- 通过定义数据模型和访问控制策略,实现对用户信息的合规访问和管理,从而保护用户的隐私和数据安全 + diff --git a/build-tools/bin/run.config b/build-tools/bin/run.config index 3970fcd4..1c79b289 100644 --- a/build-tools/bin/run.config +++ b/build-tools/bin/run.config @@ -1,6 +1,45 @@ #config your enviroment -#fill with your node ip and port, example:10.10.10.10:9000 +#Note:Once you modify any of these configuration items, you need to re-run ./compile.sh. + +#fill with your node ip and channel_listen_port, example: 0.0.0.0:20200 #if you have more than one node ,you can put them with separator"," -#for example: 10.10.10.10:9000,10:11:11:11:9000 -blockchain.node.address= +#for example: 0.0.0.0:20200,0:0:0:1:20200 +blockchain_address= + +#this build tool supports FISCO BCOS 2.0 and FISCO BCOS 3.0 +#if you want to build on FISCO BCOS 2.0, please fill with "2". +#if you want to build on FISCO BCOS 3.0, please fill with "3". +#and default value is "2" with FISCO BCOS 2.0. +blockchain_fiscobcos_version= + +#your organization name, used for communication on blockchain. +org_id= + +#amop_id +amop_id= + +#chain id +chain_id= + +#group id +group_id= + +#sdk use sm ssl, 0:非国密;1:国密 +sdk_sm_crypto= + +#Configure your database information +#persistence_type is "mysql" or "redis" +persistence_type= +mysql_address= +mysql_database= +mysql_username= +mysql_password= +redis_address= +redis_password= +#This variable is used to distinguish the environment. You can use "dev" to set the development environment, +#"stg" to set the test environment, "prd" to set the production environment. +#If you do not set it, the system will use allOrg as the environment by default. +#It is not recommended. Production use default configuration +#If you use the default values, you may encounter the problem of '160001 no permission for this cns' +cns_profile_active=prd diff --git a/build-tools/bin/run.sh b/build-tools/bin/run.sh index 8dd242c8..7276ae67 100644 --- a/build-tools/bin/run.sh +++ b/build-tools/bin/run.sh @@ -3,19 +3,22 @@ current_path=$(pwd) source_code_dir=$current_path"/../.." echo $source_code_dir -chmod 755 web3sdk.sh cd $source_code_dir if [ -d dist/ ];then - rm -rf dist/ + rm -rf dist/app + rm -rf dist/conf + rm -rf dist/*.jar fi -gradle clean build -x test +chmod u+x gradlew + +./gradlew clean build -x checkMain -x checkTest -x spotbugsMain -x spotbugsTest -x test cp -r ./build-tools/* dist/ cd dist/bin -chmod +x ./*.sh -./setup.sh "com.webank.weid.contract" "$source_code_dir" +chmod u+x ./*.sh +./setup.sh "com.webank.weid.contract" "$source_code_dir" $@ diff --git a/build-tools/bin/setup.sh b/build-tools/bin/setup.sh index 1d86dd4b..e80d7df0 100644 --- a/build-tools/bin/setup.sh +++ b/build-tools/bin/setup.sh @@ -1,13 +1,16 @@ #!/bin/bash -SOLC=$(which fisco-solc) -WEB3J="../bin/web3sdk.sh" +source run.config + java_source_code_dir=$2 -temp_file=$(date +%s)".temp" config_file=${java_source_code_dir}/dist/bin/run.config app_xml_config_dir=${java_source_code_dir}/dist/conf/ -app_xml_config_tpl=${java_source_code_dir}/src/main/resources/applicationContext.xml.tpl -app_xml_config=${java_source_code_dir}/src/main/resources/applicationContext.xml +app_xml_config_tpl=${java_source_code_dir}/src/main/resources/fisco.properties.tpl +app_xml_config=${java_source_code_dir}/src/main/resources/fisco.properties +weid_config_tpl=${java_source_code_dir}/src/main/resources/weidentity.properties.tpl +weid_config=${java_source_code_dir}/src/main/resources/weidentity.properties + +JAVA_OPTS='-Djdk.tls.namedGroups="secp256r1,secp256k1"' CLASSPATH=${java_source_code_dir}/dist/conf @@ -34,7 +37,7 @@ function check_jdk() fi else JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + which java >/dev/null 2>&1 || echo "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." @@ -42,23 +45,6 @@ function check_jdk() } -function compile_contract() -{ - cd ../contracts/ - - package="com.webank.weid.contract" - output_dir="${java_source_code_dir}/dist/output" - echo "output_dir is $output_dir" - local files=$(ls ./*.sol) - for itemfile in ${files} - do - local item=$(basename ${itemfile} ".sol") - ${SOLC} --abi --bin -o ${output_dir} ${itemfile} - echo "${output_dir}/${item}.bin, ${output_dir}, ${package} " - ${WEB3J} solidity generate ${output_dir}"/"${item}".bin" ${output_dir}"/"${item}".abi" -o ${output_dir} -p ${package} - done -} - function replace_java_contract() { @@ -71,33 +57,51 @@ function replace_java_contract() function modify_config() { echo "begin to modify sdk config..." - weid_address=$(cat weIdContract.address) - cpt_address=$(cat cptController.address) - issuer_address=$(cat authorityIssuer.address) - export WEID_ADDRESS=${weid_address} - export CPT_ADDRESS=${cpt_address} - export ISSUER_ADDRESS=${issuer_address} - MYVARS='${BLOCKCHIAN_NODE_INFO}:${WEID_ADDRESS}:${CPT_ADDRESS}:${ISSUER_ADDRESS}' + hash=$(cat hash) + export FISCO_BCOS_VERSION=${FISCO_BCOS_VERSION} + export CNS_PROFILE_ACTIVE=${CNS_PROFILE_ACTIVE} + export GROUP_ID=${GROUP_ID} + export SDK_SM_CRYPTO=${SDK_SM_CRYPTO} + + MYVARS='${FISCO_BCOS_VERSION}:${CNS_PROFILE_ACTIVE}:${GROUP_ID}:${SDK_SM_CRYPTO}' envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} cp ${app_xml_config} ${app_xml_config_dir} + export ORG_ID=${ORG_ID} + export AMOP_ID=${AMOP_ID} + export PERSISTENCE_TYPE=${persistence_type} + export MYSQL_ADDRESS=${MYSQL_ADDRESS} + export MYSQL_DATABASE=${MYSQL_DATABASE} + export MYSQL_USERNAME=${MYSQL_USERNAME} + export MYSQL_PASSWORD=${MYSQL_PASSWORD} + export BLOCKCHIAN_NODE_INFO=${BLOCKCHIAN_NODE_INFO} + + NODEVAR='${ORG_ID}:${AMOP_ID}:${PERSISTENCE_TYPE}:${MYSQL_ADDRESS}:${MYSQL_DATABASE}:${MYSQL_USERNAME}:${MYSQL_PASSWORD}:${BLOCKCHIAN_NODE_INFO}' + envsubst ${NODEVAR} < ${weid_config_tpl} >${weid_config} + cp ${weid_config} ${app_xml_config_dir} echo "modify sdk config finished..." } function clean_config() { echo "begin to clean config..." - cd ${java_source_code_dir}/dist - if [ -d bin/ ];then - rm -rf bin/ + cd ${java_source_code_dir} + if [ -f weIdContract.address ];then + rm -f weIdContract.address + fi + if [ -f cptController.address ];then + rm -f cptController.address fi - if [ -d contracts/ ];then - rm -rf contracts/ + if [ -f authorityIssuer.address ];then + rm -f authorityIssuer.address fi - if [ -d output/ ];then - rm -rf output/ + if [ -f evidenceController.address ];then + rm -f evidenceController.address fi - if [ -f ${app_xml_config} ];then - rm -f ${app_xml_config} + if [ -f specificIssuer.address ];then + rm -f specificIssuer.address + fi + if [ -f hash ];then + rm -f hash fi echo "clean finished..." } @@ -106,8 +110,9 @@ function gradle_build_sdk() { #run gradle build echo "Begin to compile java code......" - - node_addr=$(grep "blockchain.node.address" $config_file |awk -F"=" '{print $2}') + + node_addr=$(grep "blockchain_address" $config_file |awk -F"=" '{print $2}') + bcos_version=$(grep "blockchain_fiscobcos_version" $config_file |awk -F"=" '{print $2}') OLD_IFS="$IFS" IFS="," array=($node_addr) @@ -115,23 +120,41 @@ function gradle_build_sdk() content= for var in ${array[@]} do - if [ ! -z ${content} ];then - content="${content}\n" - fi - content="${content}WeIdentity@$var" + if [[ $bcos_version == 1 ]]; + then + content="${content}WeIdentity@$var," + else + content="${content}$var," + fi + done - export BLOCKCHIAN_NODE_INFO=$(echo -e ${content}) - export WEID_ADDRESS="0x0" - export CPT_ADDRESS="0x0" - export ISSUER_ADDRESS="0x0" - MYVARS='${BLOCKCHIAN_NODE_INFO}:${WEID_ADDRESS}:${CPT_ADDRESS}:${ISSUER_ADDRESS}' + + export BLOCKCHIAN_NODE_INFO=$(echo -e ${content}) + export FISCO_BCOS_VERSION=${bcos_version} + export CNS_PROFILE_ACTIVE=${cns_profile_active} + export GROUP_ID=${group_id} + export SDK_SM_CRYPTO=${sdk_sm_crypto} + + MYVARS='${FISCO_BCOS_VERSION}:${CNS_PROFILE_ACTIVE}:${GROUP_ID}:${SDK_SM_CRYPTO}' envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} + + export ORG_ID=${org_id} + export AMOP_ID=${amop_id} + export PERSISTENCE_TYPE=${persistence_type} + export MYSQL_ADDRESS=${mysql_address} + export MYSQL_DATABASE=${mysql_database} + export MYSQL_USERNAME=${mysql_username} + export MYSQL_PASSWORD=${mysql_password} + NODEVAR='${ORG_ID}:${AMOP_ID}:${PERSISTENCE_TYPE}:${MYSQL_ADDRESS}:${MYSQL_DATABASE}:${MYSQL_USERNAME}:${MYSQL_PASSWORD}:${BLOCKCHIAN_NODE_INFO}' + envsubst ${NODEVAR} < ${weid_config_tpl} >${weid_config} cd ${java_source_code_dir}/ if [ -d dist/ ];then - rm -rf dist/ + rm -rf dist/app + rm -rf dist/conf + rm -rf dist/*.jar fi - gradle clean build -x test + ./gradlew clean build -x checkMain -x checkTest -x spotbugsMain -x spotbugsTest -x test echo "compile java code done." } @@ -144,19 +167,18 @@ function deploy_contract() CLASSPATH=${CLASSPATH}:${jar_file} done - java -cp "$CLASSPATH" com.webank.weid.contract.deploy.DeployContract ${temp_file} - dos2unix ${temp_file} + java ${JAVA_OPTS} -cp "$CLASSPATH" com.webank.weid.contract.deploy.DeployContract ${chain_id} $1 echo "contract deployment done." } function main() { - compile_contract ${1} ${2} ../output/ - replace_java_contract + # compile_contract ${1} ${2} ../output/ + # replace_java_contract gradle_build_sdk - deploy_contract + deploy_contract $3 modify_config clean_config } -main +main $@ diff --git a/build-tools/contracts/AuthorityIssuerController.sol b/build-tools/contracts/AuthorityIssuerController.sol deleted file mode 100644 index f58fd460..00000000 --- a/build-tools/contracts/AuthorityIssuerController.sol +++ /dev/null @@ -1,100 +0,0 @@ -pragma solidity ^0.4.4; -import "./AuthorityIssuerData.sol"; -import "./RoleController.sol"; - -/** - * @title AuthorityIssuerController - * Issuer contract manages authority issuer info. - */ - -contract AuthorityIssuerController { - - AuthorityIssuerData private authorityIssuerData; - RoleController private roleController; - - // Event structure to store tx records - uint constant private OPERATION_ADD = 0; - uint constant private OPERATION_REMOVE = 1; - uint constant private RETURN_CODE_SUCCESS = 0; - uint constant private RETURN_CODE_FAILURE_ALREADY_EXISTS = 500201; - uint constant private RETURN_CODE_FAILURE_NOT_EXIST = 500202; - uint constant private RETURN_CODE_FAILURE_NO_PERMISSION = 500203; - event AuthorityIssuerRetLog(uint operation, uint retCode, address addr); - - // Constructor. - function AuthorityIssuerController( - address authorityIssuerDataAddress, - address roleControllerAddress - ) public { - authorityIssuerData = AuthorityIssuerData(authorityIssuerDataAddress); - roleController = RoleController(roleControllerAddress); - } - - function addAuthorityIssuer( - address addr, - bytes32[16] attribBytes32, - int[16] attribInt, - bytes accValue - ) - public - { - if (authorityIssuerData.isAuthorityIssuer(addr)) { - AuthorityIssuerRetLog(OPERATION_ADD, RETURN_CODE_FAILURE_ALREADY_EXISTS, addr); - return; - } else if (!roleController.checkPermission(tx.origin, roleController.MODIFY_AUTHORITY_ISSUER())) { - AuthorityIssuerRetLog(OPERATION_ADD, RETURN_CODE_FAILURE_NO_PERMISSION, addr); - return; - } else { - authorityIssuerData.addAuthorityIssuerFromAddress(addr, attribBytes32, attribInt, accValue); - AuthorityIssuerRetLog(OPERATION_ADD, RETURN_CODE_SUCCESS, addr); - } - } - - function removeAuthorityIssuer(address addr) public { - if (!authorityIssuerData.isAuthorityIssuer(addr)) { - AuthorityIssuerRetLog(OPERATION_REMOVE, RETURN_CODE_FAILURE_NOT_EXIST, addr); - return; - } else if (!roleController.checkPermission(tx.origin, roleController.MODIFY_AUTHORITY_ISSUER())) { - AuthorityIssuerRetLog(OPERATION_REMOVE, RETURN_CODE_FAILURE_NO_PERMISSION, addr); - return; - } else { - authorityIssuerData.deleteAuthorityIssuerFromAddress(addr); - AuthorityIssuerRetLog(OPERATION_REMOVE, RETURN_CODE_SUCCESS, addr); - } - } - - function getAllAuthorityIssuerAddress() public constant returns (address[]) { - // solidity 0.4.4 restrictions, use per-index access - uint datasetLength = authorityIssuerData.getDatasetLength(); - address[] memory issuerArray = new address[](datasetLength); - for (uint index = 0; index < datasetLength; index++) { - issuerArray[index] = authorityIssuerData.getAuthorityIssuerFromIndex(index); - } - return issuerArray; - } - - function getAuthorityIssuerInfoNonAccValue(address addr) - public - constant - returns ( - bytes32[], - int[] - ) - { - // Due to the current limitations of bcos web3j, return dynamic bytes32 and int array instead. - bytes32[16] memory allBytes32; - int[16] memory allInt; - (allBytes32, allInt) = authorityIssuerData.getAuthorityIssuerInfoNonAccValue(addr); - bytes32[] memory finalBytes32 = new bytes32[](16); - int[] memory finalInt = new int[](16); - for (uint index = 0; index < 16; index++) { - finalBytes32[index] = allBytes32[index]; - finalInt[index] = allInt[index]; - } - return (finalBytes32, finalInt); - } - - function isAuthorityIssuer(address addr) public constant returns (bool) { - return authorityIssuerData.isAuthorityIssuer(addr); - } -} \ No newline at end of file diff --git a/build-tools/contracts/AuthorityIssuerData.sol b/build-tools/contracts/AuthorityIssuerData.sol deleted file mode 100644 index c0cfe8c8..00000000 --- a/build-tools/contracts/AuthorityIssuerData.sol +++ /dev/null @@ -1,110 +0,0 @@ -pragma solidity ^0.4.4; -import "./RoleController.sol"; - -/** - * @title AuthorityIssuerData - * Authority Issuer data contract. - */ - -contract AuthorityIssuerData { - struct AuthorityIssuer { - // [0]: name - bytes32[16] attribBytes32; - // [0]: create date - int[16] attribInt; - bytes accValue; - } - - // Mapping key: address (WeIdentity DID address), value: Authority Issuer instance. - mapping (address => AuthorityIssuer) private authorityIssuerMap; - // Array used to index and count the address (WeIdentity DID address). Depends on mapping, no standalone creator. - address[] private authorityIssuerArray; - - RoleController private roleController; - - // Constructor. - function AuthorityIssuerData(address addr) public { - roleController = RoleController(addr); - } - - function isAuthorityIssuer(address addr) public constant returns (bool) { - // Use LOCAL ARRAY INDEX here, not the RoleController data. - // The latter one might lose track in the fresh-deploy or upgrade case. - for (uint index = 0; index < authorityIssuerArray.length; index++) { - if (authorityIssuerArray[index] == addr) { - return true; - } - } - return false; - } - - function addAuthorityIssuerFromAddress( - address addr, - bytes32[16] attribBytes32, - int[16] attribInt, - bytes accValue - ) - public - { - if (isAuthorityIssuer(addr)) { - return; - } - if (!roleController.checkPermission(tx.origin, roleController.MODIFY_AUTHORITY_ISSUER())) { - return; - } - roleController.addRole(addr, roleController.ROLE_AUTHORITY_ISSUER()); - AuthorityIssuer memory authorityIssuer = - AuthorityIssuer(attribBytes32, attribInt, accValue); - authorityIssuerMap[addr] = authorityIssuer; - authorityIssuerArray.push(addr); - } - - function deleteAuthorityIssuerFromAddress(address addr) public { - if (!isAuthorityIssuer(addr)) { - return; - } - if (!roleController.checkPermission(tx.origin, roleController.MODIFY_AUTHORITY_ISSUER())) { - return; - } - roleController.removeRole(addr, roleController.ROLE_AUTHORITY_ISSUER()); - delete authorityIssuerMap[addr]; - uint datasetLength = authorityIssuerArray.length; - for (uint index = 0; index < datasetLength; index++) { - if (authorityIssuerArray[index] == addr) { break; } - } - if (index != datasetLength-1) { - authorityIssuerArray[index] = authorityIssuerArray[datasetLength-1]; - } - delete authorityIssuerArray[datasetLength-1]; - authorityIssuerArray.length--; - } - - function getDatasetLength() public constant returns (uint) { - return authorityIssuerArray.length; - } - - function getAuthorityIssuerFromIndex(uint index) public constant returns (address) { - return authorityIssuerArray[index]; - } - - function getAuthorityIssuerInfoNonAccValue(address addr) - public - constant - returns ( - bytes32[16], - int[16] - ) - { - bytes32[16] memory allBytes32; - int[16] memory allInt; - for (uint index = 0; index < 16; index++) { - allBytes32[index] = authorityIssuerMap[addr].attribBytes32[index]; - allInt[index] = authorityIssuerMap[addr].attribInt[index]; - } - return (allBytes32, allInt); - } - - function getAuthorityIssuerInfoAccValue(address addr) public constant returns (bytes) { - return authorityIssuerMap[addr].accValue; - } -} \ No newline at end of file diff --git a/build-tools/contracts/CommitteeMemberController.sol b/build-tools/contracts/CommitteeMemberController.sol deleted file mode 100644 index 7f803e31..00000000 --- a/build-tools/contracts/CommitteeMemberController.sol +++ /dev/null @@ -1,74 +0,0 @@ -pragma solidity ^0.4.4; -import "./CommitteeMemberData.sol"; -import "./RoleController.sol"; - -/** - * @title CommitteeMemberController - * Issuer contract manages authority issuer info. - */ - -contract CommitteeMemberController { - - CommitteeMemberData private committeeMemberData; - RoleController private roleController; - - // Event structure to store tx records - uint constant private OPERATION_ADD = 0; - uint constant private OPERATION_REMOVE = 1; - uint constant private RETURN_CODE_SUCCESS = 0; - uint constant private RETURN_CODE_FAILURE_ALREADY_EXISTS = 500251; - uint constant private RETURN_CODE_FAILURE_NOT_EXIST = 500252; - uint constant private RETURN_CODE_FAILURE_NO_PERMISSION = 500253; - event CommitteeRetLog(uint operation, uint retCode, address addr); - - // Constructor. - function CommitteeMemberController( - address committeeMemberDataAddress, - address roleControllerAddress - ) - public - { - committeeMemberData = CommitteeMemberData(committeeMemberDataAddress); - roleController = RoleController(roleControllerAddress); - } - - function addCommitteeMember(address addr) public { - if (committeeMemberData.isCommitteeMember(addr)) { - CommitteeRetLog(OPERATION_ADD, RETURN_CODE_FAILURE_ALREADY_EXISTS, addr); - return; - } else if (!roleController.checkPermission(tx.origin, roleController.MODIFY_COMMITTEE())) { - CommitteeRetLog(OPERATION_ADD, RETURN_CODE_FAILURE_NO_PERMISSION, addr); - return; - } else { - committeeMemberData.addCommitteeMemberFromAddress(addr); - CommitteeRetLog(OPERATION_ADD, RETURN_CODE_SUCCESS, addr); - } - } - - function removeCommitteeMember(address addr) public { - if (!committeeMemberData.isCommitteeMember(addr)) { - CommitteeRetLog(OPERATION_REMOVE, RETURN_CODE_FAILURE_NOT_EXIST, addr); - return; - } else if (!roleController.checkPermission(tx.origin, roleController.MODIFY_COMMITTEE())) { - CommitteeRetLog(OPERATION_REMOVE, RETURN_CODE_FAILURE_NO_PERMISSION, addr); - return; - } else { - committeeMemberData.deleteCommitteeMemberFromAddress(addr); - CommitteeRetLog(OPERATION_REMOVE, RETURN_CODE_SUCCESS, addr); - } - } - - function getAllCommitteeMemberAddress() public constant returns (address[]) { - // Per-index access - uint datasetLength = committeeMemberData.getDatasetLength(); - address[] memory memberArray = new address[](datasetLength); - for (uint index = 0; index < datasetLength; index++) { - memberArray[index] = committeeMemberData.getCommitteeMemberAddressFromIndex(index); - } - return memberArray; - } - - function isCommitteeMember(address addr) public constant returns (bool) { - return committeeMemberData.isCommitteeMember(addr); - } -} \ No newline at end of file diff --git a/build-tools/contracts/CommitteeMemberData.sol b/build-tools/contracts/CommitteeMemberData.sol deleted file mode 100644 index ecc11a0d..00000000 --- a/build-tools/contracts/CommitteeMemberData.sol +++ /dev/null @@ -1,67 +0,0 @@ -pragma solidity ^0.4.4; -import "./RoleController.sol"; - -/** - * @title CommitteeMemberData - * CommitteeMember data contract. - */ - -contract CommitteeMemberData { - // Array used to index and record the address of committee member. - address[] private committeeMemberArray; - - RoleController private roleController; - - function CommitteeMemberData(address addr) public { - roleController = RoleController(addr); - } - - function isCommitteeMember(address addr) public constant returns (bool) { - // Use LOCAL ARRAY INDEX here, not the RoleController data. - // The latter one might lose track in the fresh-deploy or upgrade case. - for (uint index = 0; index < committeeMemberArray.length; index++) { - if (committeeMemberArray[index] == addr) { - return true; - } - } - return false; - } - - function addCommitteeMemberFromAddress(address addr) public { - if (isCommitteeMember(addr)) { - return; - } - if (!roleController.checkPermission(tx.origin, roleController.MODIFY_COMMITTEE())) { - return; - } - roleController.addRole(addr, roleController.ROLE_COMMITTEE()); - committeeMemberArray.push(addr); - } - - function deleteCommitteeMemberFromAddress(address addr) public { - if (!isCommitteeMember(addr)) { - return; - } - if (!roleController.checkPermission(tx.origin, roleController.MODIFY_COMMITTEE())) { - return; - } - roleController.removeRole(addr, roleController.ROLE_COMMITTEE()); - uint datasetLength = committeeMemberArray.length; - for (uint index = 0; index < datasetLength; index++) { - if (committeeMemberArray[index] == addr) { break; } - } - if (index != datasetLength-1) { - committeeMemberArray[index] = committeeMemberArray[datasetLength-1]; - } - delete committeeMemberArray[datasetLength-1]; - committeeMemberArray.length--; - } - - function getDatasetLength() public constant returns (uint) { - return committeeMemberArray.length; - } - - function getCommitteeMemberAddressFromIndex(uint index) public constant returns (address) { - return committeeMemberArray[index]; - } -} \ No newline at end of file diff --git a/build-tools/contracts/CptController.sol b/build-tools/contracts/CptController.sol deleted file mode 100644 index ca92089f..00000000 --- a/build-tools/contracts/CptController.sol +++ /dev/null @@ -1,165 +0,0 @@ -pragma solidity ^0.4.4; - -import "./CptData.sol"; -import "./WeIdContract.sol"; - -contract CptController { - - uint constant private CPT_NOT_EXIST = 500301; - uint constant private AUTHORITY_ISSUER_CPT_ID_EXCEED_MAX = 500302; - uint constant private CPT_PUBLISHER_NOT_EXIST = 500303; - - CptData private cptData; - WeIdContract private weIdContract; - - function CptController( - address cptDataAddress, - address weIdContractAddress - ) - public - { - cptData = CptData(cptDataAddress); - weIdContract = WeIdContract(weIdContractAddress); - } - - event RegisterCptRetLog( - uint retCode, - uint cptId, - int cptVersion - ); - - event UpdateCptRetLog( - uint retCode, - uint cptId, - int cptVersion - ); - - function registerCpt( - address publisher, - int[8] intArray, - bytes32[8] bytes32Array, - bytes32[128] jsonSchemaArray, - uint8 v, - bytes32 r, - bytes32 s - ) - public - returns (bool) - { - if (!weIdContract.isIdentityExist(publisher)) { - RegisterCptRetLog(CPT_PUBLISHER_NOT_EXIST, 0, 0); - return false; - } - - uint cptId = cptData.getCptId(publisher); - if (cptId == 0) { - RegisterCptRetLog(AUTHORITY_ISSUER_CPT_ID_EXCEED_MAX, 0, 0); - return false; - } - int cptVersion = 1; - intArray[0] = cptVersion; - cptData.putCpt(cptId, publisher, intArray, bytes32Array, jsonSchemaArray, v, r, s); - - RegisterCptRetLog(0, cptId, cptVersion); - return true; - } - - function updateCpt( - uint cptId, - address publisher, - int[8] intArray, - bytes32[8] bytes32Array, - bytes32[128] jsonSchemaArray, - uint8 v, - bytes32 r, - bytes32 s - ) - public - returns (bool) - { - if (!weIdContract.isIdentityExist(publisher)) { - UpdateCptRetLog(CPT_PUBLISHER_NOT_EXIST, 0, 0); - return false; - } - - if (cptData.isCptExist(cptId)) { - int[8] memory cptIntArray = cptData.getCptIntArray(cptId); - int cptVersion = cptIntArray[0] + 1; - intArray[0] = cptVersion; - int created = cptIntArray[1]; - intArray[1] = created; - cptData.putCpt(cptId, publisher, intArray, bytes32Array, jsonSchemaArray, v, r, s); - UpdateCptRetLog(0, cptId, cptVersion); - return true; - } else { - UpdateCptRetLog(CPT_NOT_EXIST, 0, 0); - return false; - } - } - - function queryCpt( - uint cptId - ) - public - constant - returns ( - address publisher, - int[] intArray, - bytes32[] bytes32Array, - bytes32[] jsonSchemaArray, - uint8 v, - bytes32 r, - bytes32 s) - { - publisher = cptData.getCptPublisher(cptId); - intArray = getCptDynamicIntArray(cptId); - bytes32Array = getCptDynamicBytes32Array(cptId); - jsonSchemaArray = getCptDynamicJsonSchemaArray(cptId); - (v, r, s) = cptData.getCptSignature(cptId); - } - - function getCptDynamicIntArray( - uint cptId - ) - public - constant - returns (int[]) - { - int[8] memory staticIntArray = cptData.getCptIntArray(cptId); - int[] memory dynamicIntArray = new int[](8); - for (uint i = 0; i < 8; i++) { - dynamicIntArray[i] = staticIntArray[i]; - } - return dynamicIntArray; - } - - function getCptDynamicBytes32Array( - uint cptId - ) - public - constant - returns (bytes32[]) - { - bytes32[8] memory staticBytes32Array = cptData.getCptBytes32Array(cptId); - bytes32[] memory dynamicBytes32Array = new bytes32[](8); - for (uint i = 0; i < 8; i++) { - dynamicBytes32Array[i] = staticBytes32Array[i]; - } - return dynamicBytes32Array; - } - - function getCptDynamicJsonSchemaArray( - uint cptId - ) - public - constant - returns (bytes32[]) - { - bytes32[128] memory staticBytes32Array = cptData.getCptJsonSchemaArray(cptId); - bytes32[] memory dynamicBytes32Array = new bytes32[](128); - for (uint i = 0; i < 128; i++) { - dynamicBytes32Array[i] = staticBytes32Array[i]; - } - return dynamicBytes32Array; - } -} \ No newline at end of file diff --git a/build-tools/contracts/CptData.sol b/build-tools/contracts/CptData.sol deleted file mode 100644 index e2f4d768..00000000 --- a/build-tools/contracts/CptData.sol +++ /dev/null @@ -1,175 +0,0 @@ -pragma solidity ^0.4.4; - -import "./AuthorityIssuerData.sol"; - -contract CptData { - - uint constant private AUTHORITY_ISSUER_MAX_CPT_ID = 1999999; - - uint authority_issuer_start_id = 100; - - uint none_authority_issuer_start_id = 2000000; - - AuthorityIssuerData private authorityIssuerData; - - function CptData( - address authorityIssuerDataAddress - ) - public - { - authorityIssuerData = AuthorityIssuerData(authorityIssuerDataAddress); - } - - struct Signature { - uint8 v; - bytes32 r; - bytes32 s; - } - - struct Cpt { - //store the weid address of cpt publisher - address publisher; - //intArray[0] store cpt version, int[1] store created, int[2] store updated and left are preserved int fields - int[8] intArray; - //all are preserved bytes32 fields - bytes32[8] bytes32Array; - //store json schema - bytes32[128] jsonSchemaArray; - //store signature - Signature signature; - } - - mapping (uint => Cpt) private cptMap; - - function putCpt( - uint cptId, - address cptPublisher, - int[8] cptIntArray, - bytes32[8] cptBytes32Array, - bytes32[128] cptJsonSchemaArray, - uint8 cptV, - bytes32 cptR, - bytes32 cptS - ) - public - returns (bool) - { - Signature memory cptSignature = Signature({v: cptV, r: cptR, s: cptS}); - cptMap[cptId] = Cpt({publisher: cptPublisher, intArray: cptIntArray, bytes32Array: cptBytes32Array, jsonSchemaArray:cptJsonSchemaArray, signature: cptSignature}); - return true; - } - - function getCptId( - address publisher - ) - public - constant - returns - (uint cptId) - { - if (authorityIssuerData.isAuthorityIssuer(publisher)) { - cptId = authority_issuer_start_id++; - if (cptId > AUTHORITY_ISSUER_MAX_CPT_ID) { - cptId = 0; - } - } else { - cptId = none_authority_issuer_start_id++; - } - } - - function getCpt( - uint cptId - ) - public - constant - returns ( - address publisher, - int[8] intArray, - bytes32[8] bytes32Array, - bytes32[128] jsonSchemaArray, - uint8 v, - bytes32 r, - bytes32 s) - { - Cpt memory cpt = cptMap[cptId]; - publisher = cpt.publisher; - intArray = cpt.intArray; - bytes32Array = cpt.bytes32Array; - jsonSchemaArray = cpt.jsonSchemaArray; - v = cpt.signature.v; - r = cpt.signature.r; - s = cpt.signature.s; - } - - function getCptPublisher( - uint cptId - ) - public - constant - returns (address publisher) - { - Cpt memory cpt = cptMap[cptId]; - publisher = cpt.publisher; - } - - function getCptIntArray( - uint cptId - ) - public - constant - returns (int[8] intArray) - { - Cpt memory cpt = cptMap[cptId]; - intArray = cpt.intArray; - } - - function getCptJsonSchemaArray( - uint cptId - ) - public - constant - returns (bytes32[128] jsonSchemaArray) - { - Cpt memory cpt = cptMap[cptId]; - jsonSchemaArray = cpt.jsonSchemaArray; - } - - function getCptBytes32Array( - uint cptId - ) - public - constant - returns (bytes32[8] bytes32Array) - { - Cpt memory cpt = cptMap[cptId]; - bytes32Array = cpt.bytes32Array; - } - - function getCptSignature( - uint cptId - ) - public - constant - returns (uint8 v, bytes32 r, bytes32 s) - { - Cpt memory cpt = cptMap[cptId]; - v = cpt.signature.v; - r = cpt.signature.r; - s = cpt.signature.s; - } - - function isCptExist( - uint cptId - ) - public - constant - returns (bool) - { - int[8] memory intArray = getCptIntArray(cptId); - if (intArray[0] != 0) { - return true; - } else { - return false; - } - } -} \ No newline at end of file diff --git a/build-tools/contracts/RoleController.sol b/build-tools/contracts/RoleController.sol deleted file mode 100644 index f0468603..00000000 --- a/build-tools/contracts/RoleController.sol +++ /dev/null @@ -1,134 +0,0 @@ -pragma solidity ^0.4.4; - -/** - * @title RoleController - * This contract provides basic authentication control which defines who (address) - * belongs to what specific role and has what specific permission. - */ - -contract RoleController { - /** - * Role related Constants. - */ - uint constant public ROLE_AUTHORITY_ISSUER = 100; - uint constant public ROLE_COMMITTEE = 101; - uint constant public ROLE_ADMIN = 102; - - /** - * Operation related Constants. - */ - uint constant public MODIFY_AUTHORITY_ISSUER = 200; - uint constant public MODIFY_COMMITTEE = 201; - uint constant public MODIFY_ADMIN = 202; - uint constant public MODIFY_KEY_CPT = 203; - - mapping (address => bool) private authorityIssuerRoleBearer; - mapping (address => bool) private committeeMemberRoleBearer; - mapping (address => bool) private adminRoleBearer; - - function RoleController() public { - authorityIssuerRoleBearer[msg.sender] = true; - adminRoleBearer[msg.sender] = true; - committeeMemberRoleBearer[msg.sender] = true; - } - - /** - * Public common checkPermission logic. - */ - function checkPermission( - address addr, - uint operation - ) public constant returns (bool) - { - if (operation == MODIFY_AUTHORITY_ISSUER) { - if (adminRoleBearer[addr] || committeeMemberRoleBearer[addr]) { - return true; - } - } - if (operation == MODIFY_COMMITTEE) { - if (adminRoleBearer[addr]) { - return true; - } - } - if (operation == MODIFY_ADMIN) { - if (adminRoleBearer[addr]) { - return true; - } - } - if (operation == MODIFY_KEY_CPT) { - if (authorityIssuerRoleBearer[addr]) { - return true; - } - } - return false; - } - - /** - * Add Role. - */ - function addRole( - address addr, - uint role - ) public - { - if (role == ROLE_AUTHORITY_ISSUER) { - if (checkPermission(tx.origin, MODIFY_AUTHORITY_ISSUER)) { - authorityIssuerRoleBearer[addr] = true; - } - } - if (role == ROLE_COMMITTEE) { - if (checkPermission(tx.origin, MODIFY_COMMITTEE)) { - committeeMemberRoleBearer[addr] = true; - } - } - if (role == ROLE_ADMIN) { - if (checkPermission(tx.origin, MODIFY_ADMIN)) { - adminRoleBearer[addr] = true; - } - } - } - - /** - * Remove Role. - */ - function removeRole( - address addr, - uint role - ) public - { - if (role == ROLE_AUTHORITY_ISSUER) { - if (checkPermission(tx.origin, MODIFY_AUTHORITY_ISSUER)) { - authorityIssuerRoleBearer[addr] = false; - } - } - if (role == ROLE_COMMITTEE) { - if (checkPermission(tx.origin, MODIFY_COMMITTEE)) { - committeeMemberRoleBearer[addr] = false; - } - } - if (role == ROLE_ADMIN) { - if (checkPermission(tx.origin, MODIFY_ADMIN)) { - adminRoleBearer[addr] = false; - } - } - } - - /** - * Check Role. - */ - function checkRole( - address addr, - uint role - ) public constant returns (bool) - { - if (role == ROLE_AUTHORITY_ISSUER) { - return authorityIssuerRoleBearer[addr]; - } - if (role == ROLE_COMMITTEE) { - return committeeMemberRoleBearer[addr]; - } - if (role == ROLE_ADMIN) { - return adminRoleBearer[addr]; - } - } -} diff --git a/build-tools/contracts/WeIdContract.sol b/build-tools/contracts/WeIdContract.sol deleted file mode 100644 index 0b40c011..00000000 --- a/build-tools/contracts/WeIdContract.sol +++ /dev/null @@ -1,35 +0,0 @@ -pragma solidity ^0.4.4; - -contract WeIdContract{ - - mapping(address => uint) changed; - - modifier onlyOwner(address identity, address actor) { - require (actor == identity); - _; - } - - event WeIdAttributeChanged( - address indexed identity, - bytes32 key, - bytes value, - uint previousBlock, - int updated - ); - - function getLatestRelatedBlock(address identity) public constant returns (uint) { - return changed[identity]; - } - - function setAttribute(address identity, bytes32 key,bytes value,int updated) public onlyOwner(identity, msg.sender){ - WeIdAttributeChanged(identity, key, value, changed[identity],updated); - changed[identity] = block.number; - } - - function isIdentityExist(address identity) public constant returns (bool) { - if(0x0 != identity && 0 != changed[identity]){ - return true; - } - return false; - } -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 286e4abc..7536dfcc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,54 @@ +// Due to a bug of spotbugs, the following lines have to be defined on top as well +buildscript { + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:2.4.3" +// classpath "org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:1.1.2" + } + +} + +plugins { + id 'com.github.spotbugs' version '4.7.0' + id "com.github.hierynomus.license-report" version "0.15.0" +} +import com.github.spotbugs.snom.SpotBugsTask + +def gradleVer = "4" +println "gradleVersion:" + gradle.gradleVersion +if (gradle.gradleVersion.startsWith("6") + || gradle.gradleVersion.startsWith("5") + || gradle.gradleVersion.startsWith("4.10") + || gradle.gradleVersion.startsWith("4.9") + || gradle.gradleVersion.startsWith("4.8") + || gradle.gradleVersion.startsWith("4.7")) { + println "Gradle with version >= 4.7 detected" + gradleVer = "5" +} else { + println "Gradle with version < 4.7 detected" +} + apply plugin: 'maven' apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' -apply plugin: 'jacoco' +apply plugin: 'io.spring.dependency-management' +//apply plugin: 'jsonschema2pojo' + +if (!gradle.startParameter.isOffline()) { + apply plugin: 'checkstyle' + apply plugin: 'jacoco' + apply plugin: 'signing' +} -version = "1.0.0" +group 'com.webank' + +version = "0.0.0" +def versionFile = file("VERSION") +versionFile.eachLine { line -> + version = line +} +println 'Current product version: ' + version +def repo ="${repoType}" // Specify JDK version - may vary in different scenarios sourceCompatibility = 1.8 @@ -13,39 +57,44 @@ targetCompatibility = 1.8 [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' // In this section you declare where to find the dependencies of your project repositories { - maven { - url "http://maven.aliyun.com/nexus/content/groups/public/" + if (!gradle.startParameter.isOffline()) { + mavenLocal() + if ("cn" == repo) { + println "use cn repo" + maven {url "http://maven.aliyun.com/nexus/content/groups/public/"} + } else { + println "use default repo" + mavenCentral() + } + maven { url "https://oss.sonatype.org/content/repositories/snapshots" } + maven { url "https://oss.sonatype.org/content/groups/public/" } + maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } + maven { url 'https://jitpack.io' } + } else { + maven { + url 'dependencies' + } } - - mavenLocal() - mavenCentral() } List lombok = [ - 'org.projectlombok:lombok:1.16.14' + "org.projectlombok:lombok:1.18.10" ] +def log4j_version="2.20.0" List logger = [ - "org.slf4j:jul-to-slf4j:1.7.10", - "org.apache.logging.log4j:log4j-api:2.1", - "org.apache.logging.log4j:log4j-core:2.1", - "org.apache.logging.log4j:log4j-slf4j-impl:2.1", - "org.apache.logging.log4j:log4j-web:2.1" + "org.slf4j:jul-to-slf4j:1.7.30", + "org.apache.logging.log4j:log4j-api:$log4j_version", + "org.apache.logging.log4j:log4j-core:$log4j_version", + "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version", + "org.apache.logging.log4j:log4j-web:$log4j_version", + "org.apache.logging.log4j:log4j-jcl:$log4j_version", + "com.lmax:disruptor:3.3.7" ] -def spring_version = "4.1.8.RELEASE" -List spring = [ - "org.springframework:spring-core:$spring_version", - "org.springframework:spring-beans:$spring_version", - "org.springframework:spring-context:$spring_version", - "org.springframework:spring-tx:$spring_version", - "org.springframework:spring-jdbc:$spring_version", - "org.springframework:spring-test:$spring_version" -] // junit test List junit = [ - "junit:junit:4.12", - "org.springframework:spring-test:$spring_version" + "junit:junit:4.13.1" ] List apache_commons = [ @@ -55,41 +104,118 @@ List apache_commons = [ ] List jmockit = [ - "org.jmockit:jmockit:1.9" + "org.jmockit:jmockit:1.47" ] -// In this section you declare the dependencies for your production and test code -List jackson = [ - "com.fasterxml.jackson.core:jackson-databind:2.8.8.1", - 'io.netty:netty-all:4.1.15.Final', - 'io.netty:netty-tcnative:2.0.0.Final', - 'com.google.guava:guava:19.0', - 'com.github.fge:json-schema-validator:2.2.6', - 'org.apache.httpcomponents:httpclient:4.5.2', - 'org.bouncycastle:bcprov-jdk15on:1.54', - 'com.lambdaworks:scrypt:1.4.0', - 'com.squareup:javapoet:1.7.0', - 'io.reactivex:rxjava:1.2.4', - 'com.github.jnr:jnr-unixsocket:0.15' +def jackson_version="2.14.2" +List json = [ + "com.fasterxml.jackson.core:jackson-databind:$jackson_version", + "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version", + "com.fasterxml.jackson.module:jackson-module-jsonSchema:$jackson_version", + "org.jsonschema2pojo:jsonschema2pojo-core:1.1.2", + "org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:1.1.2", + "com.networknt:json-schema-validator:1.0.71", ] -// In this section you declare the dependencies for your production and test code -dependencies { - compile logger, spring, lombok, apache_commons, jackson - runtime logger, spring, lombok, apache_commons, jackson - testCompile logger, spring, lombok, junit, jmockit - compile files('lib/web3sdk.jar') - runtime files('lib/web3sdk.jar') +def gson_version = "2.10.1" +List gson = [ + "com.google.code.gson:gson:$gson_version" +] + +List mysql_driver = [ + "mysql:mysql-connector-java:8.0.20", // todo runtime + "org.apache.commons:commons-dbcp2:2.5.0" +] + +List redisson = [ + "org.redisson:redisson:3.20.0" +] + +List zxing = [ + "com.google.zxing:core:3.3.3", + "com.google.zxing:javase:3.3.3" +] + +List rpc = [ + 'org.smartboot.socket:aio-core:1.4.2', + 'org.smartboot.socket:aio-pro:1.4.2' +] + +List pdfbox = [ + "org.apache.pdfbox:pdfbox:2.0.24" +] + +List protobuf = [ + "com.google.protobuf:protobuf-java:3.22.2" +] + +List caffeine = [ + "com.github.ben-manes.caffeine:caffeine:2.8.0" +] + +List oval = [ + "net.sf.oval:oval:3.2.1" +] + +List xstream = [ + "com.thoughtworks.xstream:xstream:1.4.20" +] + +List spring = [ + "org.springframework:spring-core:5.3.21", + "org.springframework:spring-context:5.3.25" +] + +List ipfs = [ + 'com.github.ipfs:java-ipfs-api:v1.3.3' +] + + +configurations { + localDeps + all*.exclude group: "io.netty", module: "netty-tcnative" } -jacocoTestReport { - reports { - xml.enabled true - html.enabled false - } +configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } -check.dependsOn jacocoTestReport +dependencies { + localDeps 'org.projectlombok:lombok:1.18.10' + if (!gradle.startParameter.isOffline()) { + compile logger, lombok, apache_commons, json, mysql_driver, redisson, zxing, rpc, pdfbox, protobuf, caffeine, oval, gson, spring, xstream,ipfs + compile("com.webank:weid-blockchain:3.1.1-rc.1") + + compile fileTree(dir: 'lib', include: '*.jar') + implementation 'com.google.guava:guava:31.1-jre' + implementation group: 'commons-codec', name: 'commons-codec', version: '1.15' + implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13' + implementation group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.15' + annotationProcessor lombok + + testCompile logger, lombok, apache_commons, json, junit, jmockit, rpc, pdfbox, protobuf, caffeine, oval, spring, gson, xstream + testAnnotationProcessor lombok + } + if (gradleVer.startsWith("4")) { + if (gradle.startParameter.isOffline()) { + compile fileTree(dir: 'dist/lib', include: '*.jar') + } + } + if (gradleVer.startsWith("5")) { + if (!gradle.startParameter.isOffline()) { + compileOnly 'org.projectlombok:lombok:1.18.10' + annotationProcessor 'org.projectlombok:lombok:1.18.10' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.10' + testCompileOnly 'org.projectlombok:lombok:1.18.10' + } else { + compileOnly files('dist/lib/lombok-1.18.10.jar') + annotationProcessor files('dist/lib/lombok-1.18.10.jar') + testAnnotationProcessor files('dist/lib/lombok-1.18.10.jar') + testCompileOnly files('dist/lib/lombok-1.18.10.jar') + compile fileTree(dir: 'dist/lib', include: '*.jar') + } + } +} sourceSets { main { @@ -110,10 +236,48 @@ sourceSets { } } +processResources { + exclude '**/**' +} + +clean { + delete "dist" +} + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from 'build/docs/javadoc' +} + +//tasks.withType(Javadoc).all { enabled = false} + +test { + systemProperty "jdk.tls.namedGroups", "${jdkTlsNamedGroups}" + jvmArgs "-javaagent:${classpath.find { it.name.contains("jmockit") }.absolutePath}" + doFirst { + copy { + from file('src/main/resources/WeDPR_dynamic_lib') + into 'src/test/resources/WeDPR_dynamic_lib' + } + } +} + +artifacts { + archives jar + archives sourcesJar + archives javadocJar +} + jar { + baseName = project.name destinationDir file('dist/app') - archiveName project.name +'-'+version+'.jar' - + archiveName project.name + "-" + version + ".jar" + exclude '**/*.xml' exclude '**/*.properties' @@ -122,14 +286,171 @@ jar { from file('src/main/resources/') into 'dist/conf' } - copy { - from configurations.runtime - into 'dist/lib' + if (!gradle.startParameter.isOffline()) { + copy { + from configurations.runtime + from configurations.testCompile.allArtifacts.files + from configurations.testCompile + from configurations.localDeps + into 'dist/lib' + } } - copy { - from file('.').listFiles().findAll { File f -> (f.name.endsWith('.bat') || f.name.endsWith('.sh') || f.name.endsWith('.env')) } - into 'dist' + } +} + +if (!gradle.startParameter.isOffline()) { + jacocoTestReport { + reports { + xml.enabled true + html.enabled false } } + + jacoco { + toolVersion = "0.8.5" + } + + check.dependsOn jacocoTestReport + + checkstyle { +// ignoreFailures false + ignoreFailures true //todo + showViolations true + toolVersion '8.12' + configProperties.projectDir = project.projectDir + checkstyleMain.configFile = new File(project.projectDir, '/config/checkstyle/webank_google_checks.xml') + checkstyleTest.configFile = new File(project.projectDir, '/config/checkstyle/webank_google_checks.xml') + } + + tasks.withType(Checkstyle) { + include '**/*.java' + exclude '**/contract/deploy/*.java' + exclude '**/contract/deploy/v1/*.java' + exclude '**/contract/deploy/v2/*.java' + exclude '**/contract/v1/*.java' + exclude '**/contract/v2/*.java' + exclude '**/protocol/response/timestamp/wesign/*.java' + exclude '**/protocol/request/timestamp/wesign/*.java' + reports { + xml.enabled false + html.enabled true + } + } + + spotbugs { + ignoreFailures = true // todo + showProgress = true + toolVersion = "4.2.2" + effort = "max" + reportLevel = "low" + excludeFilter = file("${project.rootDir}/config/spotbugs/spotbugs_filter.xml") + } + + tasks.withType(SpotBugsTask) { + reports { + xml.enabled false + html.enabled true + html.stylesheet resources.text.fromFile('config/spotbugs.xsl') + } + } + + uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots") { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + + pom.project { + name project.name + packaging 'jar' + description 'WeIdentity Java SDK' + url 'https://github.com/WeBankBlockchain/WeIdentity' + + scm { + url 'scm:git@github.com:WeBankBlockchain/WeIdentity.git' + connection 'scm:git@github.com:WeBankBlockchain/WeIdentity.git' + developerConnection 'git@github.com:WeBankBlockchain/WeIdentity.git' + } + + licenses { + license { + name 'Apache License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'tonychen' + name 'tonychen' + } + } + } + } + } + } + + signing { + required { gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives + } } +gradle.taskGraph.whenReady { taskGraph -> + if (taskGraph.allTasks.any { it.name == 'build' || it.name == 'assemble' }) { + tasks.findAll { + it.name == 'signArchives' || it.name == 'signDocsJar' || it.name == 'signTestJar' + }.each { task -> + task.enabled = false + } + } +} + +// Each configuration is set to the default value +//jsonSchema2Pojo { +// +// // Location of the JSON Schema file(s). This may refer to a single file or a directory of files. +//// source = files("${sourceSets.main.output.resourcesDir}/json") +// source = files("D:\\projects\\weid\\WeIdentity\\src\\test\\resources\\default_cpt") +// +// // Target directory for generated Java source files. The plugin will add this directory to the +// // java source set so the compiler will find and compile the newly generated source files. +// targetDirectory = file("${project.buildDir}/generated-sources/new/js2p") +// +// // Package name used for generated Java classes (for types where a fully qualified name has not +// // been supplied in the schema using the 'javaType' property). +// targetPackage = 'com.webank.weid.protocol.cpt.v2' +// +//} + + +//downloadLicenses { +// ext.apacheTwo = license('Apache License, Version 2.0', 'http://opensource.org/licenses/Apache-2.0') +// ext.bsd = license('BSD License', 'http://www.opensource.org/licenses/bsd-license.php') +// +// includeProjectDependencies = true +// licenses = [ +// (group('com.myproject.foo')) : license('My Company License'), +// 'org.apache.james:apache-mime4j:0.6' : apacheTwo, +// 'org.some-bsd:project:1.0' : bsd +// ] +// +// aliases = [ +// (apacheTwo) : ['The Apache Software License, Version 2.0', 'Apache 2', 'Apache License Version 2.0', 'Apache License, Version 2.0', 'Apache License 2.0', license('Apache License', 'http://www.apache.org/licenses/LICENSE-2.0')], +// (bsd) : ['BSD', license('New BSD License', 'http://www.opensource.org/licenses/bsd-license.php')] +// ] +// +// excludeDependencies = [ +// 'com.some-other-project.bar:foobar:1.0' +// ] +// +// dependencyConfiguration = 'compile' +//} \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..5f47aaf3 --- /dev/null +++ b/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -n "$1" ] ;then + sed -i "/^repoType/crepoType=$1" gradle.properties +fi + +#build +chmod u+x gradlew + +./gradlew clean build \ No newline at end of file diff --git a/check-info.sh b/check-info.sh new file mode 100644 index 00000000..cc3eaa7a --- /dev/null +++ b/check-info.sh @@ -0,0 +1,310 @@ +#!/bin/bash + +JAVA_OPTS='-Djdk.tls.namedGroups="secp256r1,secp256k1"' +classpathDir="./dist/conf" +libDir="./dist/lib" +set -- `getopt c:l: "$@"` +while [ -n "$1" ] +do + case "$1" in + -c) + classpathDir=$2 + shift ;; + -l) + libDir=$2 + shift ;; + esac + shift +done + +# check the command is exists +function checkCommand(){ + if type $1 >/dev/null 2>&1 + then + return 1 + else + return 0 + fi +} + +# check the os version +function check_os_version() { + echo "----------------------------" + echo "1. OS Version" + echo "----------------------------" + checkCommand uname + if [ $? == 1 ] ; then + uname -a + else + echo "ERROR: no 'uname' command could be found in your OS." + fi +} + +# check the jdk version +function check_jdk_version() { + echo "----------------------------" + echo "2. JDK Version" + echo "----------------------------" + checkCommand java + if [ $? == 1 ] ; then + java -version + else + echo "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +} + +# check the gradle version +function check_gradle_version() { + echo "----------------------------" + echo "3. Gradle Version" + echo "----------------------------" + checkCommand gradle + if [ $? == 1 ] ; then + gradle -version + else + echo "WARN: GRADLE_HOME is not set and no 'gradle' command could be found in your PATH. +Please set the GRADLE_HOME variable in your environment to match the +location of your Gradle installation." + fi +} + +# check the fisco-solc version +function check_fisco_solc_version() { + echo "----------------------------" + echo "4. FISCO-SOLC Version" + echo "----------------------------" + checkCommand fisco-solc + if [ $? == 1 ] ; then + fisco-solc --version + else + echo "WARN: no 'fisco-solc' command could be found in your PATH." + fi +} + +# check the os version +check_os_version + +# check the jdk version +check_jdk_version + +# check the gradle version +check_gradle_version + +# check the fisco-solc version +check_fisco_solc_version + +if [ ! -d "$classpathDir" ]; +then + echo "ERROR: you need use -c to specify your right classpath." + exit 0 +fi +if [ ! -d "$libDir" ]; +then + echo "ERROR: you need use -l to specify your libDir." + exit 0 +fi + + +fisco_properties="$classpathDir/fisco.properties" +weidentity_properties="$classpathDir/weidentity.properties" +ca_crt="$classpathDir/ca.crt" +client_keystore="$classpathDir/client.keystore" +node_crt="$classpathDir/node.crt" +node_key="$classpathDir/node.key" +sdk_version= + +# check the user configure +function check_user_config() { + echo "----------------------------" + echo "5. User Config" + echo "----------------------------" + if [ ! -f "$fisco_properties" ]; + then + echo "ERROR: the fisco.properties does not exists." + else + echo "the fisco.properties is exists." + fi + if [ ! -f "$weidentity_properties" ]; + then + echo "ERROR: the weidentity.properties does not exists." + else + echo "the weidentity.properties is exists." + fi + if [ ! -f "$ca_crt" ]; + then + echo "ERROR: the ca.crt does not exists." + else + echo "the ca.crt is exists and the MD5 is `md5sum $ca_crt | cut -d " " -f1`" + fi + + bcos_version=$(grep "bcos\.version" $fisco_properties |awk -F"=" '{print $2}') + if [[ $bcos_version == 1* ]]; + then + if [ ! -f "$client_keystore" ]; + then + echo "ERROR: the client.keystore does not exists." + else + echo "the client.keystore is exists and the MD5 is `md5sum $client_keystore | cut -d " " -f1`" + fi + elif [[ $bcos_version == 2* ]]; + then + if [ ! -f "$node_crt" ]; + then + echo "ERROR: the node.crt does not exists." + else + echo "the node.crt is exists and the MD5 is `md5sum $node_crt | cut -d " " -f1`" + fi + if [ ! -f "$node_key" ]; + then + echo "ERROR: the node.key does not exists." + else + echo "the node.key is exists and the MD5 is `md5sum $node_key | cut -d " " -f1`" + fi + else + echo "ERROR: the bcos.version value is invalid." + fi + + blockchain_orgid=$(grep "blockchain\.orgid=" $weidentity_properties |awk -F"=" '{print $2}') + echo "the current orgid: $blockchain_orgid" + nodes=$(grep "nodes=" $weidentity_properties |awk -F"=" '{print $2}') + echo "the current nodes: $nodes" + + OLD_IFS="$IFS" + IFS="," + array=($nodes) + IFS="$OLD_IFS" + for var in ${array[@]} + do + var=${var##*@} + echo begin test $var + ip=`echo $var | cut -d : -f 1` + port=`echo $var | cut -d : -f 2` + result=`echo -e "\n" | timeout 5 telnet $ip $port 2>/dev/null | grep Connected | wc -l` + if [ $result -eq 1 ]; then + echo "Network is Open." + else + echo "Network is Closed." + fi + done +} + +# check the jar version +function check_jar_version() { + echo "----------------------------" + echo "6. Dependencies Jar Version" + echo "----------------------------" + bcos_version=$(grep "bcos\.version" $fisco_properties |awk -F"=" '{print $2}') + echo "the bcos version: $bcos_version" + isSdk=1 + for file in $libDir/* + do + file=${file##*/} + if [[ $file == weid-contract-java* ]]; + then + echo "the weid contract jar: "$file + fi + if [[ $file == weid-java-sdk* ]]; + then + isSdk=0 + echo "the weid java sdk jar: "$file + fi + if [[ $file == web3sdk*-1.* ]]; + then + if [[ $bcos_version == 1* ]]; + then + echo "the web3sdk jar: "$file + fi + fi + if [[ $file == web3sdk*-2.* ]]; + then + if [[ $bcos_version == 2* ]]; + then + echo "the web3sdk jar: "$file + fi + fi + done + + if [[ $isSdk == 1 ]]; + then + if [ -d "./dist/app/" ]; + then + for file in ./dist/app/* + do + file=${file##*/} + if [[ $file == weid-java-sdk-*.jar ]]; + then + echo "the weid java sdk jar: $file" + fi + done + fi + fi +} + +# check the node version +function check_node_version() { + echo "----------------------------" + echo "7. FISCO BCOS Version" + echo "----------------------------" + isSdk=1 + version_default=1.4 + for file in $libDir/* + do + file=${file##*/} + if [[ $file == weid-java-sdk* ]]; + then + isSdk=0 + echo "your project includes the weid-java-sdk, this is: "$file + get_the_version $file + if [[ $(echo "${sdk_version} < ${version_default}" | bc) -eq 1 ]] + then + echo "WARN: the current version of SDK does not support to check the node version, minimum version 1.4.0" + else + java ${JAVA_OPTS} -cp $libDir/*:$classpathDir/ com.webank.weid.app.AppCommand --checkversion test + fi + fi + done + if [[ $isSdk == 1 ]]; + then + if [ -d "./dist/app/" ]; + then + for file in ./dist/app/* + do + file=${file##*/} + if [[ $file == weid-java-sdk-*.jar ]]; + then + get_the_version $file + if [[ $(echo "${sdk_version} < ${version_default}" | bc) -eq 1 ]] + then + echo "WARN: the current version of SDK does not support to check the node version, minimum version 1.4.0" + else + currentDir=`pwd` + java ${JAVA_OPTS} -cp $currentDir/dist/lib/*:$currentDir/dist/app/*:$currentDir/dist/conf/ com.webank.weid.app.AppCommand --checkversion test + fi + fi + done + fi + fi +} + +function get_the_version() { + sdk_version=$1 + sdk_version=${sdk_version/.rc-/} + sdk_version=${sdk_version##*-} + sdk_version=${sdk_version%.jar} + sdk_version=${sdk_version%.*} +} + +function main() { + # check the user config + check_user_config + + # check the jar version + check_jar_version + + # check the node version + check_node_version +} + +main \ No newline at end of file diff --git a/ci/script/build-ci.sh b/ci/script/build-ci.sh deleted file mode 100644 index 61e70148..00000000 --- a/ci/script/build-ci.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -java_source_code_dir=`pwd` -temp_file=`date +%s`".temp" - -app_xml_config=${java_source_code_dir}/src/main/resources/applicationContext.xml -app_xml_config_tpl=${java_source_code_dir}/src/main/resources/applicationContext.xml.tpl - - -function modify_config() -{ - echo "begin to modify sdk config..." - weid_address=$(cat weIdContract.address) - cpt_address=$(cat cptController.address) - issuer_address=$(cat authorityIssuer.address) - export WEID_ADDRESS=${weid_address} - export CPT_ADDRESS=${cpt_address} - export ISSUER_ADDRESS=${issuer_address} - MYVARS='${BLOCKCHIAN_NODE_INFO}:${WEID_ADDRESS}:${CPT_ADDRESS}:${ISSUER_ADDRESS}' - envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} - cp ${app_xml_config} ${java_source_code_dir}/src/test/resources/ - #cat $app_xml_config - echo "modify sdk config finished..." -} - - -function gradle_build_sdk() -{ - #run gradle build - - content="WeIdentity@$NODE_IP" - export BLOCKCHIAN_NODE_INFO=${content} - export WEID_ADDRESS="0x0" - export CPT_ADDRESS="0x0" - export ISSUER_ADDRESS="0x0" - MYVARS='${BLOCKCHIAN_NODE_INFO}:${WEID_ADDRESS}:${CPT_ADDRESS}:${ISSUER_ADDRESS}' - envsubst ${MYVARS} < ${app_xml_config_tpl} >${app_xml_config} - - echo "Begin to compile java code......" - if [ -d ${java_source_code_dir}/dist ]; then - rm -rf ${java_source_code_dir}/dist - fi - gradle clean build -x test - echo "compile java code done." -} - -function deploy_contract() -{ - - CLASSPATH=${java_source_code_dir}/dist/conf - echo "begin to deploy contract..." - for jar_file in ${java_source_code_dir}/dist/lib/*.jar - do - CLASSPATH=${CLASSPATH}:${jar_file} - done - - for jar_file in ${java_source_code_dir}/dist/app/*.jar - do - CLASSPATH=${CLASSPATH}:${jar_file} - done - - java -cp "$CLASSPATH" com.webank.weid.contract.deploy.DeployContract - echo "contract deployment done." - -} - -function main() -{ - gradle_build_sdk - deploy_contract - modify_config -} - -main diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..db500ad1 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,18 @@ +coverage: + status: + project: + default: + target: 30% + threshold: null + if_not_found: success + patch: + default: + enabled: no + if_not_found: success + changes: + default: + enabled: no + if_not_found: success + ignore: + - "src/main/java/com/webank/weid/util/HttpClient.java" + - "src/test/**/*" \ No newline at end of file diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index cc6caf20..979c8fe5 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -4,5 +4,13 @@ "https://checkstyle.org/dtds/suppressions_1_2.dtd"> - + + + + + + + + + diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/webank_google_checks.xml similarity index 67% rename from config/checkstyle/checkstyle.xml rename to config/checkstyle/webank_google_checks.xml index ac0a744b..7f7f291e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/webank_google_checks.xml @@ -1,38 +1,44 @@ + "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" + "https://checkstyle.org/dtds/configuration_1_3.dtd"> - + - - - + + + + + + + + + + - - + + @@ -48,18 +54,23 @@ - + - + - + @@ -67,9 +78,9 @@ - + value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/> + @@ -111,58 +122,63 @@ + value="Package name ''{0}'' must match pattern ''{1}''."/> + value="Type name ''{0}'' must match pattern ''{1}''."/> + value="Member name ''{0}'' must match pattern ''{1}''."/> + value="Parameter name ''{0}'' must match pattern ''{1}''."/> + + + + + value="Catch parameter name ''{0}'' must match pattern ''{1}''."/> + value="Local variable name ''{0}'' must match pattern ''{1}''."/> + value="Class type name ''{0}'' must match pattern ''{1}''."/> + value="Method type name ''{0}'' must match pattern ''{1}''."/> + value="Interface type name ''{0}'' must match pattern ''{1}''."/> - - - + value="GenericWhitespace ''{0}'' is followed by whitespace."/> + + + @@ -181,21 +197,29 @@ - + + - + + + + - + - + @@ -203,13 +227,16 @@ + - + - + @@ -221,9 +248,9 @@ - + + value="Method name ''{0}'' must match pattern ''{1}''."/> @@ -233,4 +260,4 @@ - + \ No newline at end of file diff --git a/config/spotbugs/spotbugs_filter.xml b/config/spotbugs/spotbugs_filter.xml new file mode 100644 index 00000000..382185de --- /dev/null +++ b/config/spotbugs/spotbugs_filter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/intellij-java-google-style.xml b/config/webank-intellij-java-google-style.xml similarity index 54% rename from config/intellij-java-google-style.xml rename to config/webank-intellij-java-google-style.xml index 900bb507..e304742e 100644 --- a/config/intellij-java-google-style.xml +++ b/config/webank-intellij-java-google-style.xml @@ -1,229 +1,273 @@ - + - - - \ No newline at end of file diff --git a/context/v1 b/context/v1 new file mode 100644 index 00000000..5028ebe4 --- /dev/null +++ b/context/v1 @@ -0,0 +1,10 @@ +{ + "@context": { + "id": "@id", + "type": "@type", + + "weidentity": "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/vocabulary.md", + + "Secp256k1": "weidentity:Secp256k1" + } +} \ No newline at end of file diff --git a/context/vocabulary.md b/context/vocabulary.md new file mode 100644 index 00000000..428a273f --- /dev/null +++ b/context/vocabulary.md @@ -0,0 +1,47 @@ +# WeIdentity Verifiable Credentials and Representations Vocabulary +Date: 2019 / 05 / 10 + +Editors: +- Junqi Zhang (junqizhang@webank.com) +- Chaoxin Hu (chaoxinhu@webank.com) + +## Abstract +This document describes the Vocabulary of the Verifiable Credentials and Representations of WeIdentity. The purpose is to be used as the complement of the original W3C Verifiable Credentials Vocabulary (https://www.w3.org/2018/credentials/) - where a set of WeIdentity specific terms are not listed and they are illustrated here. + +## Introduction +This document describes the RDFS vocabulary description used for WeIdentity Verifiable Credentials and Representations along with the default JSON-LD Context. + +This specification makes use of the following namespaces: + +weidentity: https://fintech.webank.com/weidentity/vocab + +## Classes +### Secp256k1 + +An Secp256k1 is used for digital signatures on datasets. By default, this signature mechanism uses a ```SHA-256 digest``` and ```ECDSA signature``` with SECP256K1 as the specific algorithm-scheme to perform the digital signature, authentication, and verification. + +- Identifier +Secp256k1 +- Status +stable +- Parent Class +Signature algorithm in Proof +- Expected properties +creator, created, signature +- Signature Properties + - Default Canonicalization Algorithm: https://w3id.org/rdf#URDNA2015 + - Default Signature Algorithm: http://www.w3.org/2000/09/xmldsig#rsa-sha256 + +The example below shows how a basic JSON-LD signature is expressed in a JSON-LD snippet. Note that the signature property is directly embedded in the object. The signature algorithm specifies how the signature can be generated and verified. + +```java +{ + "@context": ["https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1"] + "signature": { + "type": "Secp256k1", + "creator": "did:weid:0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "created": "2018-11-05T13:12:54Z", + "signature": "OGCzNGVkMzVmMmQ31DIyOWM32MzQzNmEx3goYzI4ZDY3NjI4NTIy5Tk=" + } +} +``` \ No newline at end of file diff --git a/context/weidentity-logo.png b/context/weidentity-logo.png new file mode 100644 index 00000000..792eab8a Binary files /dev/null and b/context/weidentity-logo.png differ diff --git a/dist/conf/endpoint-data.properties b/dist/conf/endpoint-data.properties new file mode 100644 index 00000000..e69de29b diff --git a/dist/conf/fisco.properties.tpl b/dist/conf/fisco.properties.tpl new file mode 100644 index 00000000..e368fa5d --- /dev/null +++ b/dist/conf/fisco.properties.tpl @@ -0,0 +1,65 @@ +# Fisco-bcos blockchain node related properties + +####################################################################################################### +# # +# fisco bcos 2 or 3 version config # +# # +####################################################################################################### +# Version +bcos.version=${FISCO_BCOS_VERSION} + + +####################################################################################################### +# # +# contract address config # +# # +####################################################################################################### +# contract address +weId.contractaddress= +cpt.contractaddress= +issuer.contractaddress= +evidence.contractaddress= +specificissuer.contractaddress= + +# This variable is used to distinguish the environment. You can use "dev" to set the development environment, +# "stg" to set the test environment, "prd" to set the production environment, +# If you do not set it, the system will use allOrg as the environment by default. +# It is not recommended. Production use default configuration +cns.profile.active=${CNS_PROFILE_ACTIVE} + +####################################################################################################### +# # +# web3sdk connection config # +# # +####################################################################################################### +# blockchain connection params +web3sdk.timeout=30 +web3sdk.core-pool-size=100 +web3sdk.max-pool-size=200 +web3sdk.queue-capacity=1000 +web3sdk.keep-alive-seconds=60 + + +####################################################################################################### +# # +# fisco bcos 2.0 related config # +# # +####################################################################################################### +# Fisco-Bcos 2.x params, including Group ID and Encrypt Type +group.id=1 + +####################################################################################################### +# # +# fisco bcos node cert related config # +# # +####################################################################################################### +# Fisco-Bcos sdk SSL encrypt type, 0:ECDSA, 1:SaM2 +sdk.sm-crypto=${SDK_SM_CRYPTO} +# fisco-bcos sdk cert path contains[ca.crt,sdk.crt,sdk.key] +# if sdk.sm-crypto is true, contains [gm] directory, and gm dir contains [gmca.crt,gmsdk.crt,gmsdk.key,gmensdk.crt,gmensdk.key] +sdk.cert-path=resources/conf + +# amop public key of pem and private key of p12 configuration +amop.pub-path=resources/conf/amop/consumer_public_key.pem +amop.pri-path=resources/conf/amop/consumer_private_key.p12 +amop.p12-password=123456 diff --git a/dist/conf/log4j2.xml b/dist/conf/log4j2.xml new file mode 100644 index 00000000..67a52c5e --- /dev/null +++ b/dist/conf/log4j2.xml @@ -0,0 +1,100 @@ + + + + ../logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/Makefile b/docs/en/Makefile new file mode 100644 index 00000000..298ea9e2 --- /dev/null +++ b/docs/en/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/en/conf.py b/docs/en/conf.py new file mode 100644 index 00000000..a1eda1b2 --- /dev/null +++ b/docs/en/conf.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'weid-java-sdk' +copyright = '(2018)Webank Co. Ltd.' +author = 'weidentity team' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = 'version' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinxcontrib.mermaid'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = ['.rst', '.md'] +# source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'index' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'weidentity-java-sdk.tex', 'weid-java-sdk Documentation', + 'weidentity team', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'weid-java-sdk', 'weid-java-sdk Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'weid-java-sdk', 'weid-java-sdk Documentation', + author, 'weid-java-sdk', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] \ No newline at end of file diff --git a/docs/en/docs/README.rst b/docs/en/docs/README.rst new file mode 100644 index 00000000..ef147d0a --- /dev/null +++ b/docs/en/docs/README.rst @@ -0,0 +1,32 @@ +WeIdentity JAVA SDK +=================== + +-------------- + +Overview +---------- + +WeIdentity Java SDK provides a Java library suite to manage WeIdentity. +Currently, it supports local key management, digital ID (WeIdentity +DID) management, standard attestation (WeIdentity Credential) management, +Authority Issuer and Claim Protocol Type (CPT) management. It also provides +functionalities to work on FISCO-BCOS blockchain to deploy and run smart +contracts. More features and applications will be supported in near future. + +About +-------- + +- WeIdentity Project related smart contract code will require FISCO-BCOS + and WeIdentity Java SDK to function. See + `WeIdentity Project `__ for details. + +Contact Us +------------- + +Email: weidentity@webank.com + +License +----------- + +This project is released under +`LGPLv3 `__. diff --git a/docs/en/index.rst b/docs/en/index.rst new file mode 100644 index 00000000..d1a22fa5 --- /dev/null +++ b/docs/en/index.rst @@ -0,0 +1,11 @@ +.. role:: raw-html-m2r(raw) + :format: html + +.. include:: docs/README.rst + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + Back to HomePage + diff --git a/docs/en/make.bat b/docs/en/make.bat new file mode 100644 index 00000000..7893348a --- /dev/null +++ b/docs/en/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..e95c6b46 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,13 @@ +docutils == 0.12 +sphinx == 2.2.0 +sphinx-rtd-theme == 0.4.3 +sphinx-copybutton == 0.2.6 +sphinx-version-warning == 1.1.2 +sphinx-markdown-tables == 0.0.17 +sphinxcontrib-mermaid == 0.6.0 +recommonmark == 0.5.0 +sphinx-notfound-page == 0.1 +commonmarkextensions == 0.0.5 +commonmark == 0.8.1 +git-lfs +Jinja2<3.1 diff --git a/docs/zh_CN/Makefile b/docs/zh_CN/Makefile new file mode 100644 index 00000000..298ea9e2 --- /dev/null +++ b/docs/zh_CN/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/zh_CN/conf.py b/docs/zh_CN/conf.py new file mode 100644 index 00000000..28a60eae --- /dev/null +++ b/docs/zh_CN/conf.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'weid-java-sdk' +copyright = '(2018)Webank Co. Ltd.' +author = 'weidentity team' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = 'version' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx_copybutton', + 'sphinxcontrib.mermaid', + 'sphinx.ext.mathjax', + 'sphinx_markdown_tables', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = ['.rst', '.md'] +# source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'zh_CN' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'index' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'weidentity-java-sdk.tex', 'weid-java-sdk Documentation', + 'weidentity team', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'weid-java-sdk', 'weid-java-sdk Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'weid-java-sdk', 'weid-java-sdk Documentation', + author, 'weid-java-sdk', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] \ No newline at end of file diff --git a/docs/zh_CN/docs/README.rst b/docs/zh_CN/docs/README.rst new file mode 100644 index 00000000..60ea20e2 --- /dev/null +++ b/docs/zh_CN/docs/README.rst @@ -0,0 +1,32 @@ +WeIdentity JAVA SDK +=================== + +-------------- + +总体介绍 +-------- + +WeIdentity Java SDK提供了一整套对WeIdentity进行管理操作的Java库。 +目前,SDK支持本地密钥管理、数字身份标识(WeIdentity DID)管理、 +标准化凭证(WeIdentity Credential)管理、 授权机构(Authority +Issuer)管理、 标准化模板(CPT)管理等功能, +同时也提供基于FISCO-BCOS的区块链交互、智能合约的部署与调用。 +未来还将支持更丰富的功能和应用。 + +关于 +---- + +- WeIdentity + Project对应的合约代码。需配合FISCO-BCOS和weidentity-java-sdk使用,更多详细信息详见: + `WeIdentity Project `__ + +联系我们 +-------- + +邮箱:weidentity@webank.com + +License +------- + +This project is released under +`LGPLv3 `__. diff --git a/docs/zh_CN/docs/weidentity-java-sdk-doc.rst b/docs/zh_CN/docs/weidentity-java-sdk-doc.rst new file mode 100644 index 00000000..7657ca12 --- /dev/null +++ b/docs/zh_CN/docs/weidentity-java-sdk-doc.rst @@ -0,0 +1,18645 @@ +.. role:: raw-html-m2r(raw) + :format: html + +.. _weidentity-java-sdk-doc: + +WeIdentity JAVA SDK文档 +======================= + +总体介绍 +-------- + +WeIdentity Java SDK提供了一整套对WeIdentity进行管理操作的Java库。目前,SDK支持本地密钥管理、数字身份标识(WeIdentity DID)管理、电子凭证(WeIdentity Credential)管理、授权机构(Authority Issuer)管理、CPT(Claim Protocol Type)管理、存证(Evidence)管理等功能,未来还将支持更丰富的功能和应用。 + +术语 +---- + +* 请参阅:`术语表 `_ + +部署SDK +------- + +* `WeIdentity JAVA SDK 安装部署文档 `_ + +* 开始使用之前,再次确认启动FISCO-BCOS节点已启动,确保端口可以访问。 + +整体过程快速上手 +---------------- + +按照以下流程可以完整地体验本SDK的核心功能: + +#. 注册DID:通过WeIdService的createWeId()生成一个WeIdentity DID并注册到链上; +#. 设置DID属性:分别调用WeIdService的set方法组,为此DID设置公钥、认证方式、服务端点等属性; +#. 查询DID属性:调用WeIdService的getWeIdDocumentJson()查阅生成的WeIdentity DID数据; +#. 注册授权机构:通过AuthorityIssuerService的registerAuthorityIssuer()把生成的WeIdentity DID注册成一个授权机构; +#. 查询授权机构:调用AuthorityIssuerService的queryAuthorityIssuerInfo()查阅生成的授权机构数据; +#. 注册CPT:通过CptService的registerCpt(),通过之前生成的WeIdentity DID身份创建一个你喜欢的CPT模板; +#. 查询CPT:调用CptService的queryCpt()查阅生成的CPT模板; +#. 生成凭证:通过CredentialPojoService的createCredential(),根据CPT模板,生成一份Credential; +#. 查询凭证:调用CredentialPojoService的verify(),验证此Credential是否合法; +#. 凭证存证上链:调用EvidenceService的createEvidence(),将之前生成的Credential传入,createEvidence会将传入的Credential哈希得到的Hash值存证上链; +#. 验证链上凭证存证:调用EvidenceService的verifySigner(),和链上对比,验证Credential是否被篡改。 + +代码结构说明 +------------ + +.. code-block:: text + + ├─ app:测试小工具 + ├─ config:FISCO-BCOS的合约配置 + ├─ constant:系统常量相关 + └─ contract:通过WeIdentity-Blockchain模块部署合约 + └─ deploy: 合约部署相关 + ├─ exception: 异常定义 + └─ protocol:接口参数相关定义 + ├─ base: 基础数据类型定义 + ├─ request: 接口入参定义 + └─ response: 接口出参定义 + └─ service:SDK提供的接口 + ├─ rpc:接口定义 + ├─ console:完全无依赖的接口实现 + ├─ local:基于数据库的接口实现 + └─impl:基于区块链的接口实现 + └─ suite:一些配套的工具 + ├─ cache:自定义缓存 + └─persistence:存储接口 + └─ util:工具类实现 + +基本数据结构 +-------- + +WeIdDocument +^^^^^^^^^^^^^^^^^^^^^^ + +**属性** + +com.webank.weid.protocol.base.WeIdDocumentMetadata + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - created + - Long + - 创建时间 + - + * - updated + - Long + - 更新时间 + - + * - deactivated + - Long + - 撤销时间 + - + * - versionId + - Integer + - 版本号 + - + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - WeIdentity DID + - + * - created + - Long + - 创建时间 + - + * - updated + - Long + - 更新时间 + - + * - authentication + - List\ :raw-html-m2r:`` + - + - 认证方集合,见下 + * - service + - List\ :raw-html-m2r:`` + - + - 服务端点集合,见下 + + +com.webank.weid.protocol.base.AuthenticationProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - verification method id + * - type + - String + - 类型 + - 默认为:Ed25519VerificationKey2020 + * - controller + - String + - 方法拥有人 + - verification method controller + * - publicKeyMultibase + - String + - 验证公钥 + - 使用base58编码的公钥 + + +com.webank.weid.protocol.base.ServiceProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - + * - type + - String + - 类型 + - + * - serviceEndpoint + - String + - 联系/服务方式 + - 邮箱、github个人主页等 + +**方法** + +1. toJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.WeIdDocument.toJson() + 接口定义:String toJson() + 接口描述: 将WeIdDocument转换成json格式的字符串。 + 注意:此方法转换出错会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + WeIdService weIdService = new WeIdServiceImpl(); + WeIdDocument weIdDocument = weIdService.getWeIdDocument("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a").getResult(); + String weIdDocumentJson = weIdDocument.toJson(); + + +2. fromJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.WeIdDocument.fromJson(String weIdDocumentJson) + 接口定义:WeIdDocument fromJson(String weIdDocumentJson) + 接口描述: 将json格式的WeIdDocument转换成WeIdDocument对象。 + 注意:调用fromJson(String weIdDocumentJson)的入参,必须是通过调用toJson()得到的json格式的WeIdDocument字符串,否则会抛异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + WeIdService weIdService = new WeIdServiceImpl(); + WeIdDocument weIdDocument = weIdService.getWeIdDocument("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a").getResult(); + String weIdDocumentJson = weIdDocument.toJson(); + + WeIdDocument weIdDocumentFromJson = WeIdDocument.fromJson(weIdDocumentJson); + + +Challenge +^^^^^^^^^^^^^^^^^^^^^^ + +**属性** + +com.webank.weid.protocol.base.Challenge + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - N + - WeIdentity DID + - policy提供给指定的WeIdentity DID + * - version + - Integer + - Y + - 版本 + - + * - nonce + - String + - Y + - 随机字符串 + - + +**方法** + +1. toJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.Challenge.toJson() + 接口定义:String toJson() + 接口描述: 将Challenge转换成json格式的字符串。 + 注意:此方法转换出错会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + Challenge challenge = Challenge.create("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a", "1234"); + String challengeJson = challenge.toJson(); + + +2. fromJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.Challenge.fromJson(String challengeJson) + 接口定义:Challenge fromJson(String challengeJson) + 接口描述: 将json格式的Challenge转换成Challenge对象。 + 注意:调用fromJson(String challengeJson)的入参,必须是通过调用toJson()得到的json格式的Challenge字符串,否则会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + Challenge challenge = Challenge.create("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a", "1234"); + String challengeJson = challenge.toJson(); + + Challenge challengeFromJson = Challenge.fromJson(challengeJson); + + +CredentialPojo +^^^^^^^^^^^^^^^^^^^^^^ + +**属性** + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + +**方法** + +1. toJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.CredentialPojo.toJson() + 接口定义:String toJson() + 接口描述: 将CredentialPojo转换成json格式的字符串。 + 注意:此方法转换出错会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData credentialResult = + credentialPojoService.createCredential(createCredentialPojoArgs); + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + String credentialPojoJson = response.getResult().toJson(); + + +2. fromJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.CredentialPojo.fromJson(String credentialPojoJson) + 接口定义:CredentialPojo fromJson(String credentialPojoJson) + 接口描述: 将json格式的CredentialPojo转换成CredentialPojo对象。 + 注意:调用fromJson(String credentialPojoJson)的入参,必须是通过调用toJson()得到的json格式的CredentialPojo字符串,否则会抛异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData credentialResult = + credentialPojoService.createCredential(createCredentialPojoArgs); + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + String credentialPojoJson = response.getResult().toJson(); + + CredentialPojo credentialPojoFromJson = CredentialPojo.fromJson(credentialPojoJson); + + +PresentationPolicyE +^^^^^^^^^^^^^^^^^^^^^^ + +**属性** + +com.webank.weid.protocol.base.PresentationPolicyE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - id + - Integer + - Y + - polcyId + - 策略编号 + * - orgId + - String + - Y + - 机构编号 + - + * - version + - Integer + - Y + - 版本 + - + * - policyPublisherWeId + - String + - Y + - WeIdentity DID + - 创建policy机构的WeIdentity DID + * - policy + - Map + - Y + - 策略配置 + - key: CPTID, value: 披露策略对象 + * - extra + - Map + - N + - 扩展字段 + - + +**方法** + +1. toJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.PresentationPolicyE.toJson() + 接口定义:String toJson() + 接口描述: 将PresentationPolicyE转换成json格式的字符串。 + 注意:此方法转换出错会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + PresentationPolicyE presentationPolicyE = PresentationPolicyE.create("policy.json"); + + String presentationPolicyEJson = presentationPolicyE.toJson(); + + +2. fromJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.PresentationPolicyE.fromJson(String presentationPolicyEJson) + 接口定义:PresentationPolicyE fromJson(String presentationPolicyEJson) + 接口描述: 将json格式的PresentationPolicyE转换成PresentationPolicyE对象。 + 注意:调用fromJson(String presentationPolicyEJson)的入参,必须是通过调用toJson()得到的json格式的PresentationPolicyE字符串,否则会抛异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + PresentationPolicyE presentationPolicyE = PresentationPolicyE.create("policy.json"); + + String presentationPolicyEJson = presentationPolicyE.toJson(); + + PresentationPolicyE presentationPolicyEFromJson = PresentationPolicyE.fromJson(presentationPolicyEJson); + + +PresentationE +^^^^^^^^^^^^^^^^^^^^^^ + +**属性** + +com.webank.weid.protocol.base.PresentationE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - List + - Y + - 上下文 + - + * - type + - List + - Y + - Presentation Type + - + * - credentialList + - List + - Y + - 凭证列表 + - + * - proof + - Map + - Y + - Presentation的签名信息 + - + +**方法** + +1. toJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.PresentationE.toJson() + 接口定义:String toJson() + 接口描述: 将PresentationE转换成json格式的字符串。 + 注意:此方法转换出错会抛DATA_TYPE_CASE_ERROR异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1101); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationERes = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + String presentationEJson = presentationERes.getResult().toJson(); + + +2. fromJson +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.protocol.base.PresentationE.fromJson(String presentationEJson) + 接口定义:PresentationE fromJson(String challengeJson) + 接口描述: 将json格式的PresentationE转换成PresentationE对象。 + 注意:调用fromJson(String presentationEJson)的入参,必须是通过调用toJson()得到的json格式的PresentationE字符串,否则会抛异常 。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - DATA_TYPE_CASE_ERROR + - 160008 + - 数据转换异常 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1101); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationERes = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + String presentationEJson = presentationERes.getResult().toJson(); + + PresentationE presentationE = PresentationE.fromJson(presentationEJson); + + +3. push +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.protocol.base.PresentationE.push + 接口定义: boolean push(CredentialPojo credentialPojo) + 接口描述: 将非policy里面的Credential添加到Presentation中 + 注意:调用 push(CredentialPojo credentialPojo) 添加完所有Credential后需要调用 commit(WeIdAuthentication weIdAuthentication) 进行重新签名,否则验证Presentation时会失败 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1101); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationERes = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + //将非policy要求的Credential添加到presentation中 + ResponseData responseNew = credentialPojoService.createCredential(createCredentialPojoArgs); + presentationERes.getResult().push(responseNew.getResult()); + +4. commit +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.protocol.base.PresentationE.commit + 接口定义: boolean commit(WeIdAuthentication weIdAuthentication) + 接口描述: 添加完Credential对Presentation重新签名处理了 + +**调用示例** + +.. code-block:: java + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1101); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationERes = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + //将非policy要求的Credential添加到presentation中 + ResponseData responseNew = credentialPojoService.createCredential(createCredentialPojoArgs); + presentationERes.getResult().push(responseNew.getResult()); + presentationERes.getResult().commit(weIdAuthentication) + + +接口简介 +-------- + +**WeIdentity Java SDK提供了多种类型的接口实现,包括依赖区块链或数据库的完整接口和没有任何依赖的简化接口,以满足用户的不同需求。** +**如果需要使用区块链或者数据库存储WeIdDocument和CPT等相关信息,以及需要权限管理和控制功能,可以使用完整接口实现;如果只需要纯功能接口,比如生成WeIdDocument、CPT和验证Credentials等功能,可以使用简化的接口实现。** +**完整接口实现包括五个主要的接口,它们分别是:WeIdService、AuthorityIssuerService、CptService、PolicyService、CredentialService / CredentialPojoService、EvidenceService。** + + +* WeIdService + +WeIdentity DID相关功能的核心接口。 + +本接口提供WeIdentity DID的创建、获取信息、设置属性等相关操作。 + + +* AuthorityIssuerService + +在WeIdentity的整体架构中,存在着可信的“授权机构”这一角色。一般来说,授权机构特指那些广为人知的、具有一定公信力的、并且有相对频繁签发Credential需求的实体。 + +本接口提供了对这类授权签发Credential的机构的注册、移除、查询信息等操作。 + + +* CptService + +任何凭证的签发,都需要将数据转换成已经注册的CPT (Claim Protocol Type)格式规范,也就是所谓的“标准化格式化数据”。相关机构事先需要注册好CPT,在此之后,签发机构会根据CPT提供符合格式的数据,进而进行凭证的签发。 + +本接口提供了对CPT的注册、更新、查询等操作。 + +* PolicyService + +策略(Policy)包含申明(Claim)策略和表述(Presentation)策略。WeIdentity采用基于哈希连接的方式对Credential做简单的选择性披露,验证方可以构建一种策略(Policy),描述Credential中哪些内容需要披露,哪些内容允许保密,策略的结构体和对应的CPT一致。 + +本接口提供了对策略Policy的注册、查询等操作。 + + +* CredentialService / CredentialPojoService + +凭证签发相关功能的核心接口。 + +本接口提供凭证的签发和验证操作、Verifiable Presentation的签发和验证操作。 + + +* EvidenceService + +凭证存证上链的相关接口。 + +本接口提供凭证的Hash存证的生成上链、链上查询及校验等操作。 + +**纯功能的简化接口实现抽取了以上完整接口实现的主要接口,归总到两个接口文件:WeIdServiceConsole和CredentialServiceConsole。** + + +* WeIdServiceConsole + +提供WeIdDocument生成、CPT生成和保存(文件)、策略(Policy)生成和保存(文件)等操作。 + + +* CredentialServiceConsole + +提供Credential生成和验证等操作。 + + + +完整接口列表(依赖区块链或数据库) +-------- + +WeIdService +^^^^^^^^^^^ + +1. createWeId +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.createWeId + 接口定义:ResponseData createWeId() + 接口描述: 内部创建公私钥,并注册WeIdentity DID, 并返回公钥、私钥以及WeIdentity DID。 + +**接口入参**\ : 无 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CreateWeIdDataResult + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.response.CreateWeIdDataResult + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - weId + - String + - 公钥WeIdentity DID格式字符串 + - 格式: did:weid:1000:0x…………………. + * - userWeIdPublicKey + - WeIdPublicKey + - + - + * - userWeIdPrivateKey + - WeIdPrivateKey + - + - + + +com.webank.weid.protocol.base.WeIdPublicKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - publicKey + - String + - 数字公钥 + - 如下调用示例返回,使用十进制数字表示 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 如下调用示例返回,使用十进制数字表示 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_KEYPAIR_CREATE_FAILED + - 100107 + - 创建密钥对失败 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥和weid不匹配 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.createWeId(); + + +.. code-block:: text + + 输出结果如下: + result:(com.webank.weid.protocol.response.CreateWeIdDataResult) + weId: did:weid:101:0xf4e5f96de0627960c8b91c1cc126f7b5cdeacbd0 + userWeIdPublicKey:(com.webank.weid.protocol.base.WeIdPublicKey) + publicKey: 3140516665390655972698269231665028730625296545812754612198268107926656717368563044260511639762256438305037318801307432426840176526241566631412406151716674 + userWeIdPrivateKey:(com.webank.weid.protocol.base.WeIdPrivateKey) + privateKey: 70694712486452850283637015242845250545254342779640874305734061338958342229003 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30005 + transactionHash: 0x7e4fcacdd296f10936e53d64c7d6470dd4ffa52e22405c86ed8f72389419821f + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK: 调用CreateWeID() + WeIdentity SDK->>WeIdentity SDK: 创建公私钥对 + WeIdentity SDK->>区块链节点: 调用智能合约 + 区块链节点->>区块链节点: 以事件的方式记录created属性和public key属性 + 区块链节点->>区块链节点: 记录当前的最新块高 + 区块链节点-->>WeIdentity SDK: 创建成功 + WeIdentity SDK-->>调用者:新创建好的WeIdentity DID以及公私钥对 + + +---- + +2. createWeId +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.createWeId + 接口定义:ResponseData createWeId(CreateWeIdArgs createWeIdArgs) + 接口描述: 根据传入的公私钥,注册WeIdentity DID,并返回WeIdentity DID。 + +**接口入参**\ : com.webank.weid.protocol.request.CreateWeIdArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 数字公钥 + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 后期鉴权使用 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 公钥WeIdentity DID格式字符串 + - 如:did:weid:1000:0x…………………. + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_PUBLICKEY_INVALID + - 100102 + - 公钥无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_ALREADY_EXIST + - 100105 + - WeIdentity DID已存在 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED + - 100108 + - 公私钥不成对 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey( + "2905679808560626772263712571437125497429146398815877180317365034921958007199576809718056336050058032599743534507469742764670961100255274766148096681073592"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("7581560237967740187496354914151086729152742173850631851769274217992481997665"); + + createWeIdArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = weIdService.createWeId(createWeIdArgs); + + +.. code-block:: text + + 输出结果如下: + result: did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30007 + transactionHash: 0x7f9e0fe2bcb0e77bad9aa5c38f8440e71a48dc29406d9ad43e12130afd211c67 + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + Note over 调用者:传入自己的WeIdentity DID及用作authentication的私钥 + 调用者->>WeIdentity SDK:调用CreateWeID() + WeIdentity SDK->>区块链节点:调用智能合约 + 区块链节点->>区块链节点: 检查调用者的身份是否和WeIdentity DID匹配    + opt 身份校验不通过 + 区块链节点-->>WeIdentity SDK:报错,提示私钥不匹配并退出 + WeIdentity SDK-->>调用者:报错退出 + end + 区块链节点->>区块链节点 : 以事件的方式记录created属性和public key属性 + 区块链节点->>区块链节点 : 记录当前的最新块高 + 区块链节点-->>WeIdentity SDK: 创建成功 + WeIdentity SDK-->>调用者:新创建好的WeIdentity DID + + +---- + + +3. createWeIdByPublicKey +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.createWeIdByPublicKey + 接口定义:ResponseData createWeIdByPublicKey(WeIdPublicKey weIdPublicKey,WeIdPrivateKey weIdPrivateKey) + 接口描述: 根据传入的公钥和代理的私钥,通过代理发交易链上注册WeIdentity DID,并返回WeIdentity DID。 + +**接口入参**\ : com.webank.weid.protocol.base.WeIdPublicKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 数字公钥,代理会根据这个公钥来创建WeID + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 公钥WeIdentity DID格式字符串 + - 如:did:weid:1000:0x…………………. + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_PUBLICKEY_INVALID + - 100102 + - 公钥无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey( + "2905679808560626772263712571437125497429146398815877180317365034921958007199576809718056336050058032599743534507469742764670961100255274766148096681073592"); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + esponseData response = weIdService.createWeIdByPublicKey(weIdPublicKey, weIdPrivateKey); + + +.. code-block:: text + + 输出结果如下: + result: did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30007 + transactionHash: 0x7f9e0fe2bcb0e77bad9aa5c38f8440e71a48dc29406d9ad43e12130afd211c67 + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + Note over 调用者:传入自己的WeIdentity DID及用作authentication的私钥 + 调用者->>WeIdentity SDK:createWeIdByPublicKey() + WeIdentity SDK->>区块链节点:调用智能合约 + 区块链节点->>区块链节点: 检查调用者的身份是否和WeIdentity DID匹配    + opt 身份校验不通过 + 区块链节点-->>WeIdentity SDK:报错,提示私钥不匹配并退出 + WeIdentity SDK-->>调用者:报错退出 + end + 区块链节点->>区块链节点 : 以事件的方式记录created属性和public key属性 + 区块链节点->>区块链节点 : 记录当前的最新块高 + 区块链节点-->>WeIdentity SDK: 创建成功 + WeIdentity SDK-->>调用者:新创建好的WeIdentity DID + +---- + +4. getWeIdDocumentJson +~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdDocumentJson + 接口定义:ResponseData getWeIdDocumentJson(String weId) + 接口描述: 根据WeIdentity DID查询WeIdentity DID Document信息,并以JSON格式返回。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - weidDocument Json + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.getWeIdDocumentJson("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a"); + + +.. code-block:: text + + 返回结果如下: + result: {"@context" : "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", + "id" : "did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a", + "authentication" : [ { + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + } ], + "service" : [ { + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + } ] + } + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +(同时也包含getWeIDDocument时序) + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK : 传入指定的WeIdentity DID + WeIdentity SDK->>区块链节点: 调用智能合约 + 区块链节点->>区块链节点: 查找记录该WeIdentity DID关联的属性事件最后一次更新时的块高 + 区块链节点-->>WeIdentity SDK: 返回 + loop 解析事件 + WeIdentity SDK->>区块链节点: 根据块高,过滤该区块里的属性事件 + 区块链节点-->>WeIdentity SDK: 返回 + WeIdentity SDK->>WeIdentity SDK: 根据块高,获取到对应区块所有交易 + WeIdentity SDK->>WeIdentity SDK: 根据交易获取交易回执 + WeIdentity SDK->>WeIdentity SDK: 根据交易回执过滤跟当前WeIdentity DID相关的属性事件 + WeIdentity SDK->>WeIdentity SDK: 根据不同的key,解析public key, authentication, service endpoint + WeIdentity SDK->>WeIdentity SDK: 组装WeIdentity Document + WeIdentity SDK->>WeIdentity SDK: 根据当前事件找到上一个事件对应的块高 + end + WeIdentity SDK-->>调用者:返回WeIdentity Document + + +---- + +5. getWeIDDocument +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdDocument + 接口定义:ResponseData getWeIdDocument(String weId) + 接口描述: 根据WeIdentity DID查询出WeIdentity DID Document对象。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocument + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - WeIdentity DID + - + * - authentication + - List\ :raw-html-m2r:`` + - + - 认证方集合,见下 + * - service + - List\ :raw-html-m2r:`` + - + - 服务端点集合,见下 + + +com.webank.weid.protocol.base.AuthenticationProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - verification method id + * - type + - String + - 类型 + - 默认为:Ed25519VerificationKey2020 + * - controller + - String + - 方法拥有人 + - verification method controller + * - publicKeyMultibase + - String + - 验证公钥 + - 使用base58编码的公钥 + + +com.webank.weid.protocol.base.ServiceProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - + * - type + - String + - 类型 + - + * - serviceEndpoint + - String + - 联系/服务方式 + - 邮箱、github个人主页等 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.getWeIdDocument("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a"); + + +.. code-block:: text + + 返回结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + authentication: + [0]: + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + service: + [0]: + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +6. getWeIdDocumentMetadata +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdDocumentMetadata + 接口定义:ResponseData getWeIdDocumentMetadata(String weId) + 接口描述: 根据WeIdentity DID查询出WeIdentity DID DocumentMetadata对象。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocument + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + com.webank.weid.protocol.base.WeIdDocumentMetadata + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - created + - Long + - 创建 + - + * - updated + - Long + - 修改 + - + * - deactivated + - boolean + - 解散 + - + * - versionId + - int + - 版本Id + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.getWeIdDocumentMetadata("did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a"); + + +.. code-block:: text + + 返回结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + created: 1686560615 + updated: 1686560615 + deactivated: false + versionId: 1 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + + +7. setService +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.setService + 接口定义:ResponseData setService(String weId, ServiceArgs setServiceArgs, WeIdPrivateKey weIdPrivateKey) + 接口描述: 根据WeIdentity DID添加Service信息。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + +com.webank.weid.protocol.request.ServiceArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - type + - String + - Y + - 类型 + - 如:drivingCardService + * - serviceEndpoint + - String + - Y + - 服务端点 + - 如:"https://weidentity.webank.com/endpoint/8377464" + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - WEID_SERVICE_TYPE_OVERLIMIT + - 100110 + - type字段超长 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + ServiceArgs setServiceArgs = new SetServiceArgs(); + setServiceArgs.setType("drivingCardService"); + setServiceArgs.setServiceEndpoint("https://weidentity.webank.com/endpoint/8377464"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + ResponseData response = weIdService.setService("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", setServiceArgs, weIdPrivateKey); + + +.. code-block:: text + + 返回结果如下: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30012 + transactionHash: 0xf4992c4d190a9338f13119125861aaa3fa86622de1ab6862d06c05c6e6d1d9be + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + Note over 调用者:传入自己的WeIdentity DID及要用作
authentication的私钥,
以及service endpoint + 调用者->>WeIdentity SDK : 调用setAuthentication来添加认证。 + WeIdentity SDK->>WeIdentity SDK:拿私钥来重新加载合约对象 + WeIdentity SDK->>区块链节点: 调用智能合约 + 区块链节点->>区块链节点: 检查调用者的身份是否和WeIdentity DID匹配    + opt 身份校验不通过 + 区块链节点-->>WeIdentity SDK:报错,提示私钥不匹配并退出 + WeIdentity SDK-->>调用者:报错退出 + end + 区块链节点->>区块链节点:将service endpoint和WeIdentity DID以及上次记录的块高写到属性事件中 + 区块链节点->>区块链节点:记录最新块高 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + + +8. setAuthentication +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.setAuthentication + 接口定义:ResponseData setAuthentication(String weId, AuthenticationArgs authenticationArgs, WeIdPrivateKey weIdPrivateKey) + 接口描述: 根据WeIdentity DID添加Authentication信息。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + +com.webank.weid.protocol.request.AuthenticationArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - owner + - String + - N + - 所有者 + - 默认为当前WeIdentity DID + * - publicKey + - String + - Y + - 数字公钥 + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + AuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); + setAuthenticationArgs.setPublicKey( + "13161444623157635919577071263152435729269604287924587017945158373362984739390835280704888860812486081963832887336483721952914804189509503053687001123007342"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + ResponseData response = weIdService.setAuthentication("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", setAuthenticationArgs, weIdPrivateKey); + + +.. code-block:: text + + 返回结果如下: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30013 + transactionHash: 0xfbf8338e7df2af0612eca5107c0d2ed75dfd7a795988687f49c010112678f847 + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + Note over 调用者:传入自己的WeIdentity DID及用作authentication的公私钥 + 调用者->>WeIdentity SDK : 调用setAuthentication来添加认证。 + WeIdentity SDK->>WeIdentity SDK:拿私钥来重新加载合约对象 + WeIdentity SDK->>区块链节点: 调用智能合约 + 区块链节点->>区块链节点: 检查调用者的身份是否和WeIdentity DID匹配    + opt 身份校验不通过 + 区块链节点-->>WeIdentity SDK:报错,提示私钥不匹配并退出 + WeIdentity SDK-->>调用者:报错退出 + end + 区块链节点->>区块链节点:将authentication和WeIdentity DID以及上次记录的块高写到属性事件中 + 区块链节点->>区块链节点:记录最新块高 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + + +9. isWeIdExist +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.isWeIdExist + 接口定义:ResponseData isWeIdExist(String weId) + 接口描述: 根据WeIdentity DID判断链上是否存在。 + + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID格式字符串 + - 如:did:weid:101:0x.... + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.isWeIdExist("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + +.. code-block:: text + + 返回结果如下: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +**时序图** + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK : 传入WeIdentity DID,调用isWeIdExist来判断是否存在。 + opt 参数校验 + Note over WeIdentity SDK:非空检查和有效性检查 + WeIdentity SDK->>WeIdentity SDK:报错,提示参数不合法并退出 + end + WeIdentity SDK->>区块链节点: 传入WeIdentity DID链上存在性校验 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + +10. isDeactivated +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.isDeactivated + 接口定义:ResponseData isDeactivated(String weId) + 接口描述: 检查WeIdentity DID是否在链上停用。 + + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID格式字符串 + - 如:did:weid:101:0x.... + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + ResponseData response = weIdService.isDeactivated("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + +.. code-block:: text + + 返回结果如下: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +11. revokeAuthentication +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.revokeAuthentication + 接口定义:ResponseData revokeAuthentication(String weId, AuthenticationArgs authenticationArgs, WeIdPrivateKey weIdPrivateKey) + 接口描述: 仅删除WeID文档中的身份验证标签-不会影响其公钥。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID字符串 + - + +com.webank.weid.protocol.request.AuthenticationArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - owner + - String + - N + - 所有者 + - 默认为当前WeIdentity DID + * - publicKey + - String + - Y + - 数字公钥 + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + AuthenticationArgs authenticationArgs = new AuthenticationArgs(); + authenticationArgs.setPublicKey( + "13161444623157635919577071263152435729269604287924587017945158373362984739390835280704888860812486081963832887336483721952914804189509503053687001123007342"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + ResponseData response = weIdService.revokeAuthentication("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", authenticationArgs, weIdPrivateKey); + + +.. code-block:: text + + 返回结果如下: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30013 + transactionHash: 0xfbf8338e7df2af0612eca5107c0d2ed75dfd7a795988687f49c010112678f847 + transactionIndex: 0 + + +---- + +12. getWeIdList +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdList + 接口定义:ResponseData> getWeIdList(Integer first, Integer last) + 接口描述: 根据块高度、索引位置和搜索方向查询数据。 + +**接口入参**\ : + +Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - first + - Integer + - + - + - + +Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - last + - Integer + - + - + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\>; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + ResponseData response = weIdService.getWeIdList(1,10); + + +.. code-block:: text + + 返回结果如下: + result: + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30013 + transactionHash: 0xfbf8338e7df2af0612eca5107c0d2ed75dfd7a795988687f49c010112678f847 + transactionIndex: 0 + + +---- + + +13. getWeIdCount +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdCount + 接口定义:ResponseData getWeIdCount() + 接口描述: 获得总weId。 + +**接口入参**\ : + +无 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + + ResponseData response = weIdService.getWeIdCount(); + + +.. code-block:: text + + 返回结果如下: + result: 123 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30013 + transactionHash: 0xfbf8338e7df2af0612eca5107c0d2ed75dfd7a795988687f49c010112678f847 + transactionIndex: 0 + + +---- + +14. getWeIdListByPubKeyList +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.WeIdService.getWeIdListByPubKeyList + 接口定义:ResponseData getWeIdListByPubKeyList(List pubKeyList) + 接口描述: 通过公钥列表获取WeID列表。 + +**接口入参**\ : com.webank.weid.protocol.base.WeIdPublicKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 数字公钥,代理会根据这个公钥来创建WeID + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否set成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + +com.webank.weid.protocol.response.WeIdListResult + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - weIdList + - List + - + - + * - errorCodeList + - List + - + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdService weIdService = new WeIdServiceImpl(); + List pubKeyList = new ArrayList<>(); + int num = 5; + for (int i = 0; i < num; i++) { + WeIdPublicKey publicKey = new WeIdPublicKey(); + publicKey.setPublicKey("13161444623157635919577071263152435729269604287924587017945158373362984739390835280704888860812486081963832887336483721952914804189509503053687001123007342"); + pubKeyList.add(publicKey); + } + + ResponseData weIdListRes = weIdService.getWeIdListByPubKeyList(pubKeyList); + + +.. code-block:: text + + 返回结果如下: + result: + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30013 + transactionHash: 0xfbf8338e7df2af0612eca5107c0d2ed75dfd7a795988687f49c010112678f847 + transactionIndex: 0 + + +---- + + +AuthorityIssuerService +^^^^^^^^^^^^^^^^^^^^^^ + +1. registerAuthorityIssuer +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.AuthorityIssuerService.registerAuthorityIssuer + 接口定义:ResponseData registerAuthorityIssuer(RegisterAuthorityIssuerArgs args) + 接口描述: 注册成为权威机构。 + 注意:这是一个需要权限的操作,目前只有合约的部署者(一般为SDK)才能正确执行。 + +**接口入参**\ : com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - authorityIssuer + - AuthorityIssuer + - Y + - + - AuthorityIssuer信息,见下 + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.AuthorityIssuer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - 授权机构WeIdentity DID + - + * - name + - String + - Y + - 授权机构名称 + - 机构名称必须小于32个字节,非空,且仅包含ASCII码可打印字符(ASCII值位于32~126) + * - created + - Long + - N + - 创建日期 + - 注册时不需要传入,SDK内置默认为当前时间 + * - accValue + - String + - Y + - 授权方累积判定值 + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL + - 100202 + - 私钥格式非法 + * - AUTHORITY_ISSUER_OPCODE_MISMATCH + - 100205 + - 操作码不匹配 + * - AUTHORITY_ISSUER_NAME_ILLEGAL + - 100206 + - 名称格式非法 + * - AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL + - 100207 + - 累计值格式非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + authorityIssuer.setName("webank1"); + authorityIssuer.setAccValue("0"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("36162289879206412028682370838615850457668262092955617990245744195910144330785"); + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); + registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuer); + registerAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29963 + transactionHash: 0x97a5cc2f4f7888e788a22e7c9bef1a293614bceec4721810511d07fc5b748f33 + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant WeIdService + participant 区块链节点 + 调用者->>AuthorityIssuerService: 调用RegisterAuthorityIssuer() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>WeIdService: 查询WeIdentity DID存在性 + WeIdService->>区块链节点: 链上查询WeIdentity DID属性 + 区块链节点-->>WeIdService: 返回查询结果 + WeIdService-->>AuthorityIssuerService: 返回查询结果 + opt 在链上不存在 + AuthorityIssuerService-->>调用者: 报错并退出 + end + AuthorityIssuerService->>区块链节点: 加载私钥,调用注册合约 + opt 身份校验 + Note over 区块链节点: 如果传入WeIdentity DID在链上不存在 + 区块链节点->>区块链节点: 报错并退出 + end + 区块链节点->>区块链节点: 权限检查,执行合约写入AuthorityIssuer信息 + 区块链节点-->>AuthorityIssuerService: 返回合约执行结果 + AuthorityIssuerService->>AuthorityIssuerService: 解析合约事件 + opt 失败,地址无效或无权限 + AuthorityIssuerService-->>调用者: 报错并退出 + end + AuthorityIssuerService-->>调用者: 返回成功 + + +---- + +2. removeAuthorityIssuer +~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.AuthorityIssuerService.removeAuthorityIssuer + 接口定义:ResponseData removeAuthorityIssuer(RemoveAuthorityIssuerArgs args) + 接口描述: 注销权威机构。 + 注意:这是一个需要权限的操作,目前只有合约的部署者(一般为SDK)才能正确执行。 + +**接口入参**\ : com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - 授权机构WeIdentity DID + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL + - 100202 + - 私钥格式非法 + * - AUTHORITY_ISSUER_OPCODE_MISMATCH + - 100205 + - 操作码不匹配 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("36162289879206412028682370838615850457668262092955617990245744195910144330785"); + + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = new RemoveAuthorityIssuerArgs(); + removeAuthorityIssuerArgs.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + removeAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29951 + transactionHash: 0xb9a2ef2a6045e0804b711e0ce39f7187de08e329160d5a5a00a1815e067f15e5 + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: 调用RemoverAuthorityIssuer() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 加载交易私钥,调用移除合约 + 区块链节点->>区块链节点: 权限检查,执行合约删除WeIdentity DID信息 + 区块链节点-->>AuthorityIssuerService: 返回合约执行结果 + AuthorityIssuerService->>AuthorityIssuerService: 解析合约事件 + opt 失败,地址无效或无权限 + AuthorityIssuerService-->>调用者: 报错并退出 + end + AuthorityIssuerService-->>调用者: 返回成功 + + +---- + +3. isAuthorityIssuer +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.AuthorityIssuerService.isAuthorityIssuer + 接口定义:ResponseData isAuthorityIssuer(String weId) + 接口描述: 根据WeIdentity DID判断是否为权威机构。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - 用于搜索权限发布者 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS + - 500202 + - 实体不存在 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + String weId = "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"; + ResponseData response = authorityIssuerService.isAuthorityIssuer(weId); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: 调用IsAuthorityIssuer() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用查询是否为授权机构合约 + 区块链节点->>区块链节点: 执行合约通过WeIdentity DID查询 + 区块链节点-->>AuthorityIssuerService: 返回查询结果 + AuthorityIssuerService-->>调用者: 返回是/否 + + +---- + +4. queryAuthorityIssuerInfo +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.AuthorityIssuerService.queryAuthorityIssuerInfo + 接口定义:ResponseData queryAuthorityIssuerInfo(String weId) + 接口描述: 根据WeIdentity DID查询权威机构信息。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - 用于搜索权限发布者 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - AuthorityIssuer + - + - 授权机构信息,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.AuthorityIssuer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - 授权机构WeIdentity DID + - + * - name + - String + - Y + - 授权机构名称 + - + * - created + - Long + - Y + - 创建日期 + - + * - accValue + - String + - Y + - 授权方累积判定值 + - + + +**注意**\ :因为Solidity 0.4.4的限制,无法正确的返回accValue,因此这里取得的accValue一定为空字符串。未来会进行修改。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS + - 500202 + - 实体不存在 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + String weId = "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"; + ResponseData response = authorityIssuerService.queryAuthorityIssuerInfo(weId); + + +.. code-block:: text + + 返回数据如: + result:(com.webank.weid.protocol.base.AuthorityIssuer) + weId: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + name: webank1 + created: 1560412556901 + accValue: + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: 调用queryAuthorityIssuerInfo() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用查询详细信息合约 + 区块链节点->>区块链节点: 执行合约通过WeIdentity DID查询 + 区块链节点-->>AuthorityIssuerService: 返回查询结果 + AuthorityIssuerService-->>调用者: 返回查询结果(非授权机构则无) + + +---- + + +5. getAllAuthorityIssuerList +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.getAllAuthorityIssuerList + 接口定义: ResponseData> getAllAuthorityIssuerList(Integer index, Integer num) + 接口描述: 查询指定范围内的issuer列表。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - index + - Integer + - Y + - 检索的开始位置 + - + * - num + - Integer + - Y + - 检索的数据条数 + - 单次最多可以检索50条 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\>; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - List + - + - 授权机构信息,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.AuthorityIssuer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - 授权机构WeIdentity DID + - + * - name + - String + - Y + - 授权机构名称 + - + * - created + - Long + - Y + - 创建日期 + - + * - accValue + - String + - Y + - 授权方累积判定值 + - + + +**注意**\ :因为Solidity 0.4.4的限制,无法正确的返回accValue,因此这里取得的accValue一定为空字符串。未来会进行修改。 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + ResponseData> response = authorityIssuerService.getAllAuthorityIssuerList(0, 2); + + +.. code-block:: text + + 返回数据如: + result: (java.util.ArrayList) + [0]: com.webank.weid.protocol.base.AuthorityIssuer + weId: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + name: webank1 + created: 1560412556901 + accValue: + [1]: com.webank.weid.protocol.base.AuthorityIssuer + weId: did:weid:101:0x48f56f6b8cd77409447014ceb060243b914cb2a9 + name: webank2 + created: 1560632118000 + accValue: + errorCode: 0 + errorMessage: success + transactionInfo:null + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: getAllAuthorityIssuerList() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用查询详细信息合约 + 区块链节点->>区块链节点: 执行合约查询指定数目的授权机构,打包返回结果 + 区块链节点-->>AuthorityIssuerService: 返回查询结果 + AuthorityIssuerService-->>调用者: 返回查询结果 + +---- + + +6. registerIssuerType +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.registerIssuerType + 接口定义: ResponseData registerIssuerType(WeIdAuthentication callerAuth, String issuerType) + 接口描述: 指定并注册不同issuer的类型,如学校、政府机构等。 + 权限说明:本方法对传入的WeIdAuthentication没有特定权限要求。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - callerAuth + - WeIdAuthentication + - Y + - weId身份信息 + - + * - issuerType + - String + - Y + - 机构类型 + - + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否注册成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - SPECIFIC_ISSUER_TYPE_ILLEGAL + - 100208 + - 机构类型非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + ResponseData> response = authorityIssuerService.registerIssuerType(weIdAuthentication, "College"); + +.. code-block:: text + + 返回数据如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo: (com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29950 + transactionHash: 0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13 + transactionIndex: 0 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: registerIssuerType() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用注册授权机构类型合约 + 区块链节点->>区块链节点: 执行合约注册授权机构类型 + 区块链节点-->>AuthorityIssuerService: 返回执行结果 + AuthorityIssuerService-->>调用者: 返回执行结果 + + +---- + + +7. addIssuerIntoIssuerType +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.addIssuerIntoIssuerType + 接口定义: ResponseData addIssuerIntoIssuerType(WeIdAuthentication callerAuth, String issuerType, String targetIssuerWeId) + 接口描述: 向指定的issuerType中添加成员。 + 权限说明:方法的调用者至少需要是Authority Issuer才能成功。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - callerAuth + - WeIdAuthentication + - Y + - weId身份信息 + - + * - issuerType + - String + - Y + - 机构类型 + - + * - targetIssuerWeId + - String + - Y + - issuer的WeIdentity DID + - + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否添加成员成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - WEID_INVALID + - 100201 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL + - 100202 + - 私钥格式非法 + * - SPECIFIC_ISSUER_TYPE_ILLEGAL + - 100208 + - 机构类型非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + ResponseData> response = authorityIssuerService.addIssuerIntoIssuerType(weIdAuthentication, "College", "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + +.. code-block:: text + + 返回数据如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo: (com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29950 + transactionHash: 0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13 + transactionIndex: 0 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: addIssuerIntoIssuerType() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用添加授权机构合约 + 区块链节点->>区块链节点: 执行合约添加授权机构 + 区块链节点-->>AuthorityIssuerService: 返回执行结果 + AuthorityIssuerService-->>调用者: 返回执行结果 + +---- + + +8. removeIssuerFromIssuerType +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.removeIssuerFromIssuerType + 接口定义: ResponseData removeIssuerFromIssuerType(WeIdAuthentication callerAuth, String issuerType, String targetIssuerWeId) + 接口描述: 移除指定issuerType里面的WeId成员。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - callerAuth + - WeIdAuthentication + - Y + - weId身份信息 + - + * - issuerType + - String + - Y + - 机构类型 + - + * - targetIssuerWeId + - String + - Y + - issuer的WeIdentity DID + - + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否移除成功 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - WEID_INVALID + - 100201 + - 无效的WeIdentity DID + * - AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL + - 100202 + - 私钥格式非法 + * - SPECIFIC_ISSUER_TYPE_ILLEGAL + - 100208 + - 机构类型非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + ResponseData> response = authorityIssuerService.removeIssuerFromIssuerType(weIdAuthentication, "College", "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + +.. code-block:: text + + 返回数据如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo: (com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29950 + transactionHash: 0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13 + transactionIndex: 0 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: removeIssuerIntoIssuerType() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用移除授权机构合约 + 区块链节点->>区块链节点: 执行合约移除授权机构 + 区块链节点-->>AuthorityIssuerService: 返回执行结果 + AuthorityIssuerService-->>调用者: 返回执行结果 + +---- + + +9. isSpecificTypeIssuer +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.isSpecificTypeIssuer + 接口定义: ResponseData isSpecificTypeIssuer(String issuerType, String targetIssuerWeId) + 接口描述: 判断issuer是否为指定机构里面的成员。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - issuerType + - String + - Y + - 机构类型 + - + * - targetIssuerWeId + - String + - Y + - issuer的WeIdentity DID + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否为指定类型中的成员 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - SPECIFIC_ISSUER_TYPE_ILLEGAL + - 100208 + - 机构类型非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST + - 500502 + - 授权人不存在 + + +**调用示例** + +.. code-block:: java + + AuthorityIssuerService authorityIssuerService = new AuthorityIssuerServiceImpl(); + String weId = "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"; + ResponseData response = authorityIssuerService.isAuthorityIssuer(weId); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant AuthorityIssuerService + participant 区块链节点 + 调用者->>AuthorityIssuerService: 调用IsAuthorityIssuer() + AuthorityIssuerService->>AuthorityIssuerService: 入参非空、格式及合法性检查 + opt 入参校验失败 + AuthorityIssuerService-->>调用者: 报错,提示参数不合法并退出 + end + AuthorityIssuerService->>区块链节点: 调用查询是否为授权机构合约 + 区块链节点->>区块链节点: 执行合约通过WeIdentity DID查询 + 区块链节点-->>AuthorityIssuerService: 返回查询结果 + AuthorityIssuerService-->>调用者: 返回是/否 + + +---- + + +10. getAllSpecificTypeIssuerList +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.AuthorityIssuerService.getAllSpecificTypeIssuerList + 接口定义: ResponseData> getAllSpecificTypeIssuerList(String issuerType, Integer index, Integer num) + 接口描述: 获取指定索引范围内的issuer列表。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - issuerType + - String + - Y + - 机构类型 + - + * - index + - Integer + - Y + - 检索的开始下标位置 + - + * - num + - Integer + - Y + - 检索数据个数 + - 单次最多可以检索50条 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\>; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - List + - issuer列表 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - AUTHORITY_ISSUER_ERROR + - 100200 + - 授权标准异常 + * - SPECIFIC_ISSUER_TYPE_ILLEGAL + - 100208 + - 机构类型非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + + +.. code-block:: text + + 返回数据如: + + +---- + + +CptService +^^^^^^^^^^ + +1. registerCpt +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CptService.registerCpt + 接口定义:ResponseData registerCpt(CptMapArgs args) + 接口描述: 传入WeIdentity DID,JsonSchema(Map类型) 和其对应的私钥,链上注册CPT,返回CPT编号和版本。 + +**接口入参**\ : com.webank.weid.protocol.request.CptMapArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, "cpt template"); + cptJsonSchema.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = { "F", "M" }; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = { "name", "gender" }; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(cptMapArgs); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1016 + cptVersion: 1 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29950 + transactionHash: 0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13 + transactionIndex: 0 + + +**时序图** + +(同时也包含重载updateCpt时序) + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK : 传入自己已有的WeIdentity DID及对应的私钥,及其jsonSchema,调用registerCpt来注册CPT。 + opt 参数校验 + Note over WeIdentity SDK:如果WeIdentity DID或者私钥为空或不匹配 + WeIdentity SDK->>WeIdentity SDK:报错,提示参数不合法并退出 + end + WeIdentity SDK->>区块链节点: 将java对象转换为合约所需的字段,调用智能合约,将CPT信息上链 + opt 身份校验 + Note over 区块链节点:如果传入WeIdentity DID在链上不存在 + 区块链节点->>区块链节点:报错,提示WeIdentity DID不存在并退出 + end + 区块链节点->>区块链节点:写入CPT信息 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + + +2. registerCpt +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.CptService.registerCpt + 接口定义: ResponseData registerCpt(CptMapArgs args, Integer cptId) + 接口描述: 传入WeIdentity DID,JsonSchema(Map类型), cptId 和其对应的私钥,链上注册指定cptId的CPT,返回CPT编号和版本。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - args + - CptMapArgs + - Y + - Map类型参数注册CPT + - + * - cptId + - Integer + - Y + - 指定的cptId + - + + +com.webank.weid.protocol.request.CptMapArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, "cpt template"); + cptJsonSchema.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = { "F", "M" }; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap propertitesMap4 = new HashMap(2); + propertitesMap4.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap4.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is id"); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchemaKeys.put("id", propertitesMap4); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = { "id", "name", "gender" }; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(cptMapArgs, 101); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 101 + cptVersion: 1 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29950 + transactionHash: 0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13 + transactionIndex: 0 + + +---- + + +3. registerCpt +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CptService.registerCpt + 接口定义:ResponseData registerCpt(CptStringArgs args) + 接口描述: 传入WeIdentity DID,JsonSchema(String类型) 和其对应的私钥,链上注册CPT,返回CPT编号和版本。 + +**接口入参**\ : com.webank.weid.protocol.request.CptStringArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - String + - Y + - 字符串类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + String jsonSchema = "{\"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\"]}"; + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(cptStringArgs); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1017 + cptVersion: 1 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29964 + transactionHash: 0xf3b039557b2d1e575e9949b3a33d34ee5c8749b55940347d18a0f7e929eda799 + transactionIndex: 0 + + +---- + + +4. registerCpt +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.CptService.registerCpt + 接口定义: ResponseData registerCpt(CptStringArgs args, Integer cptId) + 接口描述: 传入WeIdentity DID,JsonSchema(String类型) , cptId和其对应的私钥,链上注册指定cptId的CPT,返回CPT编号和版本。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - args + - CptStringArgs + - Y + - String类型参数注册CPT + - + * - cptId + - Integer + - Y + - 指定的cptId + - + + +com.webank.weid.protocol.request.CptStringArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - String + - Y + - 字符串类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + String jsonSchema = "{\"properties\" : {\"id\": {\"type\": \"string\",\"description\": \"the id of certificate owner\"}, \"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\": [\"id\", \"name\", \"age\"]}"; + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(cptStringArgs, 103); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 103 + cptVersion: 1 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29910 + transactionHash: 0xf3b039557b2d1e575e9949b3a33d34e35c8749b55940347d18a0f7e929eda799 + transactionIndex: 0 + + +---- + + +5. queryCpt +~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CptService.queryCpt + 接口定义:ResponseData queryCpt(Integer cptId) + 接口描述: 根据CPT编号查询CPT信息。 + +**接口入参**\ : java.lang.Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - cptId + - Integer + - Y + - cptId编号 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Cpt + - + - CPT内容,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.Cpt + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptJsonSchema + - Map + - Map类型的cptJsonSchema信息 + - + * - cptBaseInfo + - CptBaseInfo + - + - CPT基础数据,见下 + * - cptMetaData + - CptMetaData + - + - CPT元数据内部类,见下 + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +com.webank.weid.protocol.base.Cpt.MetaData + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptPublisher + - String + - CPT发布者的WeIdentity DID + - WeIdentity DID格式数据 + * - cptSignature + - String + - 签名数据 + - cptPublisher与cptJsonSchema拼接的签名数据 + * - updated + - long + - 更新时间 + - + * - created + - long + - 创建日期 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + Integer cptId = Integer.valueOf(1017); + ResponseData response = cptService.queryCpt(cptId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.Cpt) + cptBaseInfo:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1017 + cptVersion: 1 + cptJsonSchema:(java.util.HashMap) + $schema: http://json-schema.org/draft-04/schema# + type: object + properties:(java.util.LinkedHashMap) + age:(java.util.LinkedHashMap) + description: the age of certificate owner + type: number + gender:(java.util.LinkedHashMap) + description: the gender of certificate owner + enum:(java.util.ArrayList) + [0]:F + [1]:M + type: string + name:(java.util.LinkedHashMap) + description: the name of certificate owner + type: string + required:(java.util.ArrayList) + [0]:name + [1]:age + metaData:(com.webank.weid.protocol.base.Cpt$MetaData) + cptPublisher: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + cptSignature: G/YGY8Ftj9jPRdtr4ym+19M4/K6x9RbmRiV9JkryXeQGFr8eukDCBAcbinnNpF2N3Eo72bvxNqJOKx4ohWIus0Y= + created: 1560415607673 + updated: 0 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK : 传入指定的cptId + opt 参数校验 + Note over WeIdentity SDK:检查传入的cptId是否为空或负数 + WeIdentity SDK->>WeIdentity SDK:报错,提示weid不合法并退出 + end + WeIdentity SDK->>区块链节点: 调用合约查询链上的指定cpt对应的信息 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK->>WeIdentity SDK:根据合约返回的值构建返回的java对象 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + +6. updateCpt +~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CptService.updateCpt + 接口定义:ResponseData updateCpt(CptMapArgs args, Integer cptId) + 接口描述: 传入cptId,JsonSchema(Map类型),WeIdentity DID,WeIdentity DID所属私钥,进行更新CPT信息,更新成功版本自动+1。 + +**接口入参**\ : com.webank.weid.protocol.request.CptMapArgs,Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - args + - CptMapArgs + - Y + - CPT信息 + - 具体见下 + * - cptId + - Integer + - Y + - 发布的CPT编号 + - + + +com.webank.weid.protocol.request.CptMapArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, "cpt template"); + cptJsonSchema.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = { "F", "M" }; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = { "name", "gender" }; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + Integer cptId = Integer.valueOf(1017); + + ResponseData response = cptService.updateCpt(cptMapArgs, cptId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1017 + cptVersion: 2 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29989 + transactionHash: 0x4435fa88f9f138f14671d8baa5e5f16c69c5efa3591c4912772b9b1233af398a + transactionIndex: 0 + + +**时序图** + +(同时也包含重载updateCpt时序) + +.. mermaid:: + + sequenceDiagram + 调用者->>WeIdentity SDK : 传入自己已有的WeIdentity DID及对应的私钥,及其需新版本的jsonSchema,调用updateCpt来更新CPT。 + opt 参数校验 + Note over WeIdentity SDK:如果WeIdentity DID或者私钥为空或不匹配 + WeIdentity SDK->>WeIdentity SDK:报错,提示参数不合法并退出 + end + WeIdentity SDK->>区块链节点: 将java对象转换为合约所需的字段,调用智能合约,将更新的CPT信息上链 + opt 身份校验 + Note over 区块链节点:如果传入WeIdentity DID在链上不存在 + 区块链节点->>区块链节点:报错,提示WeIdentity DID不存在并退出 + end + 区块链节点->>区块链节点:写入CPT更新信息 + 区块链节点-->>WeIdentity SDK:返回 + WeIdentity SDK-->>调用者:返回调用结果 + + +---- + +7. updateCpt +~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CptService.updateCpt + 接口定义:ResponseData updateCpt(CptStringArgs args, Integer cptId) + 接口描述: 传入cptId,JsonSchema(String类型),WeIdentity DID,WeIdentity DID所属私钥,进行更新CPT信息,更新成功版本自动+1。 + +**接口入参**\ : com.webank.weid.protocol.request.CptStringArgs,Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - args + - CptStringArgs + - Y + - CPT信息 + - 具体见下 + * - cptId + - Integer + - Y + - 发布的CPT编号 + - + +com.webank.weid.protocol.request.CptStringArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - String + - Y + - 字符串类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + CptService cptService = new CptServiceImpl(); + + String jsonSchema = "{\"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\"]}"; + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(weIdAuthentication); + + Integer cptId = Integer.valueOf(1017); + + ResponseData response = cptService.updateCpt(cptStringArgs, cptId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1017 + cptVersion: 3 + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 29991 + transactionHash: 0x8ed8113dd1772ae74e6f12de3d3716d76a410190c3d564d5d5842b85c7005aee + transactionIndex: 0 + + +---- + +CredentialService +^^^^^^^^^^^^^^^^^ + +1. createCredential +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.createCredential + 接口定义:ResponseData createCredential(CreateCredentialArgs args) + 接口描述: 创建电子凭证,默认是original类型,还支持轻量级lite1类型和基于零知识证明的zkp类型的credential。 + +**接口入参**\ : com.webank.weid.protocol.request.CreateCredentialArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - cptId + - Integer + - Y + - CPT编号 + - + * - issuer + - String + - Y + - 发行方WeIdentity DID + - WeIdentity DID格式数据 + * - expirationDate + - Long + - Y + - 到期日 + - + * - claim + - Map + - Y + - Map类型的claim数据 + - 凭证所需数据 + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 签名所用Issuer WeIdentity DID私钥,见下 + * - type + - CredentialType + - Y + - 默认值是ORIGINAL,还支持ZKP和Lite类型 + - 创建的credential的类型 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialWrapper + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CredentialWrapper + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - credential + - Credential + - Y + - 凭证信息 + - 具体见下 + * - disclosure + - Map + - Y + - 披露属性 + - 默认为全披露 + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - JsonSchema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** +Original类型的credential生成示例: + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1551448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = credentialService.createCredential(createCredentialArgs); + + +.. code-block:: text + + 返回结果如下: + { + "errorCode":0, + "errorMessage":"success", + "result":{ + "claim":{ + "age":18, + "gender":"F", + "name":"zhangsan" + }, + "context":"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", + "cptId":2000082, + "expirationDate":1588776752, + "id":"0d633260-d31c-4155-b79d-a9eb67df7bab", + "issuanceDate":1588065179, + "issuer":"did:weid:101:0x9bd9897fcdb98428f7b152ce8a06cb16758ccd17", + "proof":{ + "created":1588065179, + "creator":"did:weid:101:0x9bd9897fcdb98428f7b152ce8a06cb16758ccd17#keys-0", + "salt":{ + "age":"exkEX", + "gender":"ya9jA", + "name":"Q4BDW" + }, + "signatureValue":"G51huya0Q4Nz4HGa+dUju3GVrR0ng+atlXeouEKe60ImLMl6aihwZsSGExOgC8KwP3sUjeiggdba3xjVE9SSI/g=", + "type":"Secp256k1" + }, + "type":[ + "VerifiableCredential", + "original" + ] + }, + "transactionInfo":null +} + +Lite类型的credential生成示例: + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1551448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + //如果不设置type为LITE1,则默认生成ORIGINAL类型 + createCredentialArgs.setType(CredentialType.LITE1); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = credentialService.createCredential(createCredentialArgs); + + +.. code-block:: text + + 返回结果如下,lite 类型的credential会比original类型的credential少salt等一些字段,更轻量: + { + "errorCode":0, + "errorMessage":"success", + "result":{ + "claim":{ + "age":18, + "gender":"F", + "name":"zhangsan" + }, + "context":"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", + "cptId":2000082, + "expirationDate":1588776636, + "id":"c85cbaea-753b-4ae7-830f-20fb718b01b7", + "issuanceDate":1588065063, + "issuer":"did:weid:101:0x9bd9897fcdb98428f7b152ce8a06cb16758ccd17", + "proof":{ + "signatureValue":"YopZgmhvi6ob9xPiROLb4p2WJ7j7RTwydGDUbonO9GEZBkpYVfcnlrbJ2H1vuyaVaoR46goJWfDWG3s1woY1/AE=", + "type":"Secp256k1" + }, + "type":[ + "VerifiableCredential", + "lite1" + ] + }, + "transactionInfo":null +} + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialService + 调用者->>CredentialService: 调用CreateCredential() + CredentialService->>CredentialService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialService->>CredentialService: 生成签发日期、生成数字签名 + CredentialService-->>调用者: 返回凭证 + + +---- + +2. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.verify + 接口定义:ResponseData verify(Credential credential); + 接口描述: 验证凭证是否正确。 + +**接口入参**\ : com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuer与签名不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_ISSUER_NOT_EXISTS + - 100407 + - WeIdentity DID不能为空 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - WeIdentity Document为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 验证签名异常 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1561448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + //创建Credential + ResponseData response = credentialService.createCredential(createCredentialArgs); + + //验证Credential + ResponseData responseVerify = credentialService.verify(response.getResult().getCredential()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +(同时也包含verifyCredentialWithSpecifiedPubKey时序) + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialService + participant CptService + participant WeIdService + participant 区块链节点 + 调用者->>CredentialService: 调用verify()或verifyCredentialWithSpecifiedPubKey() + CredentialService->>CredentialService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialService->>WeIdService: 查询WeIdentity DID存在性 + WeIdService->>区块链节点: 调用智能合约,查询WeIdentity DID属性 + 区块链节点-->>WeIdService: 返回查询结果 + WeIdService-->>CredentialService: 返回查询结果 + opt 查询不存在 + CredentialService-->>调用者: 报错并退出 + end + CredentialService->>CptService: 查询CPT存在性及Claim关联语义 + CptService->>区块链节点: 调用智能合约,查询CPT + 区块链节点-->>CptService: 返回查询结果 + CptService-->>CredentialService: 返回查询结果 + opt 不符合CPT格式要求 + CredentialService-->>调用者: 报错并退出 + end + CredentialService->>CredentialService: 验证过期、撤销与否 + opt 任一验证失败 + CredentialService-->>调用者: 报错并退出 + end + opt 未提供验签公钥 + CredentialService->>WeIdService: 查询Issuer对应公钥 + WeIdService->>区块链节点: 调用智能合约,查询Issuer的WeIdentity DID Document + 区块链节点-->>WeIdService: 返回查询结果 + WeIdService-->>CredentialService: 返回查询结果 + end + CredentialService->>CredentialService: 通过公钥与签名对比,验证Issuer是否签发此凭证 + opt 验证签名失败 + CredentialService-->>调用者: 报错并退出 + end + CredentialService-->>调用者: 返回成功 + + +---- + +3. verifyCredentialWithSpecifiedPubKey +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.verifyCredentialWithSpecifiedPubKey + 接口定义: ResponseData verifyCredentialWithSpecifiedPubKey(CredentialWrapper credentialWrapper, WeIdPublicKey weIdPublicKey) + 接口描述: 验证凭证是否正确,需传入公钥。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - credentialWrapper + - CredentialWrapper + - Y + - + - 凭证信息,见下 + * - weIdPublicKey + - WeIdPublicKey + - Y + - + - 公钥信息,见下 + + +com.webank.weid.protocol.base.CredentialWrapper + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - credential + - Credential + - Y + - 凭证信息 + - 具体见下 + * - disclosure + - Map + - N + - 披露属性 + - 默认为全披露 + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.WeIdPublicKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - publicKey + - String + - 数字公钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuer与签名不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_ISSUER_NOT_EXISTS + - 100407 + - WeIdentity DID不能为空 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - WeIdentity Document为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 验证签名异常 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1561448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + // 创建Credential + ResponseData response = credentialService.createCredential(createCredentialArgs); + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey( + "9202079291855274840499629257327649367489192973501473466426182121217769706994308329953406897395674428921435762028726727399019951049448689033610431403383875"); + + //使用公钥验证 + ResponseData responseVerify = credentialService + .verifyCredentialWithSpecifiedPubKey(response.getResult(), weIdPublicKey); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +4. getCredentialHash +~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.getCredentialHash + 接口定义:ResponseData getCredentialHash(Credential args) + 接口描述: 传入Credential信息生成Credential整体的Hash值,一般在生成Evidence时调用。 + +**接口入参**\ : com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1561448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + //创建Credentia + ResponseData response = credentialService.createCredential(createCredentialArgs); + + //获取Credentia的Hash + ResponseData responseHash = credentialService.getCredentialHash(response.getResult().getCredential()); + + +.. code-block:: text + + 返回结果如: + result: 0x06173e4b714d57565ae5ddf23c4e84cb0a9824cb72eab476303d2dd1cc0a4728 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialService + 调用者->>CredentialService: 调用GetCredentialHash() + CredentialService->>CredentialService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialService->>CredentialService: 生成凭证Hash + CredentialService-->>调用者: 返回凭证Hash + + +---- + +5. getCredentialHash +~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.getCredentialHash + 接口定义:ResponseData getCredentialHash(CredentialWrapper args) + 接口描述: 传入Credential信息生成Credential整体的Hash值,一般在生成Evidence时调用。 + +**接口入参**\ : com.webank.weid.protocol.base.CredentialWrapper + + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - credential + - Credential + - Y + - 凭证信息 + - 具体见下 + * - disclosure + - Map + - Y + - 披露属性 + - 默认为全披露 + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1561448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + //创建CredentialWrapper + ResponseData response = credentialService.createCredential(createCredentialArgs); + + //获取CredentialWrapper的Hash + ResponseData responseHash = credentialService.getCredentialHash(response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: 0x06173e4b714d57565ae5ddf23c4e84cb0a9824cb72eab476303d2dd1cc0a4728 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialService + 调用者->>CredentialService: 调用GetCredentialHash() + CredentialService->>CredentialService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialService->>CredentialService: 生成凭证Hash + CredentialService-->>调用者: 返回凭证Hash + + +6. addSignature +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialService.addSignature + 接口定义:ResponseData addSignature(List credentialList, WeIdPrivateKey weIdPrivateKey) + 接口描述:多签,在原凭证列表的基础上,创建包裹成一个新的多签凭证,由传入的私钥所签名。此凭证的CPT为一个固定值。在验证一个多签凭证时,会迭代验证其包裹的所有子凭证。本接口不支持创建选择性披露的多签凭证。 + +**接口入参**\ : java.util.ArrayList + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Credential + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - 默认为106 + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - JsonSchema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1551448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = credentialService.createCredential(createCredentialArgs); + List credList = new ArrayList<>(); + credList.add(response.getResult().getCredential()); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialArgs.setExpirationDate(expirationDate); + Credential tempCredential = + credentialService.createCredential(createCredentialArgs).getResult().getCredential(); + credentialList.add(tempCredential); + ResponseData multiSignedResp = credentialService.addSignature(credList, weIdPrivateKey); + System.out.println(multiSignedResp); + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialWrapper) + credential:(com.webank.weid.protocol.base.Credential) { + "claim": { + "credentialList": [ + { + "claim": { + "age": 18, + "gender": "F", + "id": "did:weid:101:0xe4bee5a07f282ffd3109699e21663cde0210fb64", + "name": "zhang san" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000084, + "expirationDate": 1567488114, + "id": "a8b1c030-231d-49de-9618-b5ed7f3e6d2e", + "issuanceDate": 1567401714, + "issuer": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "proof": { + "created": "1567401714", + "creator": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "signature": "GwKcDoEseYdJxI7M\/R4RAdGcV5SJoFVvg8Z53BVa76LMV8eqbX3F4rb1dWjhqI286AvPECx6uuuo9cTAKuNHRXM=", + "type": "Secp256k1" + } + }, + { + "claim": { + "age": 18, + "gender": "F", + "id": "did:weid:101:0xe4bee5a07f282ffd3109699e21663cde0210fb64", + "name": "zhang san" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000084, + "expirationDate": 1567488201, + "id": "2130908d-fb2a-4675-8bf1-727f354ca8e4", + "issuanceDate": 1567401715, + "issuer": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "proof": { + "created": "1567401715", + "creator": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "signature": "HJXDuvg2l8jRbL5ymmBSAo\/6DMKbCv3P1XoP67S+OVzSbRVDNFXY1CsqpTqT5MAkSY4+UwPLwCfXrLtHsZQ6GOo=", + "type": "Secp256k1" + } + } + ] + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 106, + "expirationDate": 1567488201, + "id": "d8642623-703f-447a-8765-dab1dab4df0a", + "issuanceDate": 1567401717, + "issuer": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "proof": { + "created": "1567401717", + "creator": "did:weid:1000:1:0x92d5472954c38375371f8bdd2bcce2e64aab1f99", + "signature": "HKXEwzDEwqte4aAUBLvQjiI3C0cw5V\/iWeKWmBs7HIG0IRzgbXnMj8kYw37y5yJE4KdsWCuehBUGuW7WdihL560=", + "type": "Secp256k1" + } + } + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialService + 调用者->>CredentialService: 调用addSignature() + CredentialService->>CredentialService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialService->>CredentialService: 生成签发日期、以原凭证列表为Claim生成数字签名 + CredentialService-->>调用者: 返回凭证 + + +---- + +EvidenceService +^^^^^^^^^^^^^^^^^ + +1. createEvidence +~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.createEvidence + 接口定义:ResponseData createEvidence(Hashable object, WeIdPrivateKey weIdPrivateKey) + 接口描述: 为一个**未曾上过链**的Object,将传入的Object计算Hash值生成存证上链,返回存证hash值。传入的私钥将会成为链上存证的签名方。此签名方和凭证的Issuer可以不是同一方。此接口返回的Hash值和generateHash()接口返回值一致。同样的传入Object可以由不同的私钥注册存证,它们的链上存证值将会共存。 + +**接口入参**\ : + +Hashable java.lang.Object + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - Object + - Hashable object + - N + - 实现了Hashable接口的任意Object + - 当前支持HashString,Credential,CredentialWrapper,CredentialPojo + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 创建的凭证hash值 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CREDENTIAL_EVIDENCE_CONTRACT_FAILURE_ILLEAGAL_INPUT + - 500401 + - Evidence参数非法 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用CreateEvidence() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>EvidenceService: 生成凭证Hash + EvidenceService->>EvidenceService: 基于凭证Hash生成签名值 + EvidenceService->>区块链节点: 调用智能合约,创建并上传凭证存证 + 区块链节点-->>EvidenceService: 返回创建结果 + opt 创建失败 + EvidenceService-->>调用者: 报错并退出 + end + EvidenceService-->>调用者: 返回成功 + +---- + +2. createEvidenceWithLogAndCustomKey / createEvidenceWithLog +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.createEvidence + 接口定义:ResponseData createEvidence(Hashable object, WeIdPrivateKey weIdPrivateKey, String log, String customKey) + 接口描述: 为一个**未曾上过链**的Object,将传入Object计算Hash值生成存证上链。此方法允许在创建存证时写入额外信息。额外信息为一个log记录,从后往前叠加存储。不同私钥发交易方的额外信息也是共存且相互独立存储的。如果您重复调用此接口,那么新写入的额外值会以列表的形式添加到之前的log列表之后。此方法还允许传入一个用户自定义的custom key,用来查询链上的存证(而不是通过hash)。 + +**接口入参**\ : + +Hashable java.lang.Object + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - Object + - Hashable object + - N + - 实现了Hashable接口的任意Object + - 当前支持Credential,CredentialWrapper,CredentialPojo + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - log + - String + - Y + - 额外信息 + - 长度不能超过2M,必须为UTF-8 + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - customKey + - String + - Y + - 用户自定索引关键字 + - 长度不能超过2M,必须为UTF-8 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 创建的凭证hash值 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CREDENTIAL_EVIDENCE_CONTRACT_FAILURE_ILLEAGAL_INPUT + - 500401 + - Evidence参数非法 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用CreateEvidence() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>EvidenceService: 生成凭证Hash + EvidenceService->>EvidenceService: 基于凭证Hash生成签名值 + EvidenceService->>区块链节点: 调用智能合约,创建并上传凭证存证及额外值 + 区块链节点-->>EvidenceService: 返回创建结果 + opt 创建失败 + EvidenceService-->>调用者: 报错并退出 + end + EvidenceService-->>调用者: 返回成功 + + +---- + +3. getEvidence +~~~~~~~~~~~~~~~~~~~ + + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.getEvidence + 接口定义:ResponseData getEvidence(String hashValue) + 接口描述: 根据传入的凭证存证hash值,在链上查找凭证在链上是否存在。如果存在,则返回所有为此hash值创建过存证的创建方,及其创建时间、额外信息。 + + +**接口入参**\ : String + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - EvidenceInfo + - 创建的凭证合约地址 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.EvidenceInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - credentialHash + - String + - 凭证Hash值 + - 是一个66个字节的字符串,以0x开头 + * - signInfo + - Map + - 存证创建者信息 + - 链上允许一个存证存在多个创建者 + +com.webank.weid.protocol.base.EvidenceSignInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - signature + - String + - 存证的签名 + - 以Base64编码的存证签名值 + * - timestamp + - String + - 存证创建时间 + - + * - logs + - List + - 额外信息列表 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用GetEvidence() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>区块链节点: 调用智能合约,查询凭证存证内容,反向构建Evidence + 区块链节点-->>EvidenceService: 返回查询结果 + opt 查询出错 + EvidenceService-->>调用者: 报错并退出 + end + EvidenceService-->>调用者: 返回成功 + +---- + +4. getEvidenceByCustomKey +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.getEvidenceByCustomKey + 接口定义:ResponseData getEvidenceByCustomKey(String customKey) + 接口描述: 根据传入的自定义索引,在链上查找凭证在链上是否存在。如果存在,则返回所有为此索引值值创建过存证的创建方,及其创建时间、额外信息。 + + +**接口入参**\ : String + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - EvidenceInfo + - 创建的凭证合约地址 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.EvidenceInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - credentialHash + - String + - 凭证Hash值 + - 是一个66个字节的字符串,以0x开头 + * - signInfo + - Map + - 存证创建者信息 + - 链上允许一个存证存在多个创建者 + +com.webank.weid.protocol.base.EvidenceSignInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - signature + - String + - 存证的签名 + - 以Base64编码的存证签名值 + * - timestamp + - String + - 存证创建时间 + - + * - logs + - List + - 额外信息列表 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用GetEvidence() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>区块链节点: 调用智能合约,查询凭证存证内容,反向构建Evidence + 区块链节点-->>EvidenceService: 返回查询结果 + opt 查询出错 + EvidenceService-->>调用者: 报错并退出 + end + EvidenceService-->>调用者: 返回成功 + +---- + +5. verifySigner +~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.verifySigner + 接口定义:ResponseData verify(CredentialPojo credentialPojo, EvidenceInfo evidenceInfo, String weId) + 接口描述: 根据传入的凭证和存证信息和WeID,从链上根据WeID的公钥,判断此存证是否合法。 + +**接口入参**\ : + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + +com.webank.weid.protocol.base.EvidenceInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - credentialHash + - String + - 凭证Hash值 + - 是一个66个字节的字符串,以0x开头 + * - signInfo + - Map + - 存证创建者信息 + - 链上允许一个存证存在多个创建者 + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - 用户WeID + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否验证成功 + - + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_SIGNATURE_BROKEN + - 100431 + - 存证签名异常 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant WeIdService + participant 区块链节点 + 调用者->>EvidenceService: 调用VerifySi + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>WeIdService: 根据存证中签名方信息,调用GetWeIdDocument()查询WeID公钥 + WeIdService->>区块链节点: 调用智能合约,查询WeID公钥 + 区块链节点-->>WeIdService: 返回查询结果 + EvidenceService->>EvidenceService: 验证存证中签名是否为与凭证Hash一致 + opt 验签失败 + EvidenceService-->>调用者: 返回验证失败,报错并退出 + end + EvidenceService-->>调用者: 返回验证成功 + +---- + +6. verifySigner(传入公钥) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.verifySigner + 接口定义:ResponseData verify(CredentialPojo credentialPojo, EvidenceInfo evidenceInfo, String weId, String publicKey) + 接口描述: 根据传入的凭证和存证信息和WeID,及传入的公钥,判断此WeID是否为存证的合法创建者。不需要链上交互。 + +**接口入参**\ : + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + +com.webank.weid.protocol.base.EvidenceInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - credentialHash + - String + - 凭证Hash值 + - 是一个66个字节的字符串,以0x开头 + * - signInfo + - Map + - 存证创建者信息 + - 链上允许一个存证存在多个创建者 + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - 用户WeID + - + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 传入公钥 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 是否验证成功 + - + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_SIGNATURE_BROKEN + - 100431 + - 存证签名异常 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - WEID_PUBLICKEY_INVALID + - 100102 + - 公钥格式非法 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant WeIdService + participant 区块链节点 + 调用者->>EvidenceService: 调用VerifySigner() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>EvidenceService: 验证存证中签名是否合法且WeID存在 + opt 验签失败 + EvidenceService-->>调用者: 返回验证失败,报错并退出 + end + EvidenceService-->>调用者: 返回验证成功 + +---- + +7. generateHash +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.rpc.EvidenceService.generateHash + 接口定义: ResponseData generateHash(T object) + 接口描述: 将传入的任意Object计算Hash值,不需网络。可以接受**任意Hashable对象**(如凭证)、**File**(Java里的文件实例)、**String**(字符串)。对于不符合类型的入参,将返回类型不支持错误。返回值为HashString,可以直接传入CreateEvidence接口用于存证创建。 + +**接口入参**\ : + +T java.lang.Object + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - Object + - T object + - N + - 任意Object + - 当前支持Hashable,File, String + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - HashString + - 创建的符合Hashable接口的存证值对象 + - 存证值,可以直接传入createEvidence用于存证上链 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - ILLEGAL_INPUT + - 160004 + - 入参非法 + + +**调用示例** + +.. code-block:: java + + CredentialService credentialService = new CredentialServiceImpl(); + EvidenceService evidenceService = new EvidenceServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(1017); + createCredentialArgs.setExpirationDate(1561448312461L); + createCredentialArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); + + // 创建Credential + ResponseData response = credentialService.createCredential(createCredentialArgs); + + // 直接将凭证传入generateHash + String hash = evidenceService.generateHash(response.getResult().getCredential()).getResult().getHash(); + + // 将凭证传入createEvidence(),将自动对Credential做hash并以Credential的hash上链 + ResponseData responseCreateEvidence = evidenceService.createEvidence(response.getResult().getCredential(), weIdPrivateKey); + // 对比hash和responseCreateEvidence.getResult()的哈希值,应为相同 + +.. code-block:: text + + 返回结果如: + result: 0xa3203e054bb7a7f0dec134c7510299869e343e8d + errorCode: 0 + errorMessage: success + transactionInfo:(com.webank.weid.protocol.response.TransactionInfo) + blockNumber: 30014 + transactionHash: 0x1f9e62fa152eb5fce859dcf81c7c0eddcbcab63c40629d1c745058c227693dae + transactionIndex: 0 + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用generateHash() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查(Hashable, File, String) + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService-->>调用者: 返回HashString及成功 + +---- + +8. addLogByHash / addLogByCustomKey +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.addLogByHash / addLogByCustomKey + 接口定义:ResponseData addLogByHash(String hashValueSupplement(仅在customKey中用到), String hashValue / customKey, String log, WeIdPrivateKey weIdPrivateKey) + 接口描述: 为一个**已经在链上存在的存证**添加额外信息记录存入其log中。有两个接口,一个是以hash值为索引,一个可以接受用户自定义索引(customKey);如果自定义索引不存在,则会使用替补hash作为上链索引。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValueSupplement + - String + - N + - + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValue + - String + - N + - + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - log + - String + - Y + - 额外信息 + - 长度不能超过2M,必须为UTF-8 + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - customKey + - String + - Y + - 用户自定索引关键字 + - 长度不能超过2M,必须为UTF-8 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant EvidenceService + participant 区块链节点 + 调用者->>EvidenceService: 调用addLog() + EvidenceService->>EvidenceService: 入参非空、格式及合法性检查 + opt 入参校验失败 + EvidenceService-->>调用者: 报错,提示参数不合法并退出 + end + EvidenceService->>区块链节点: 调用智能合约,添加额外信息 + 区块链节点-->>EvidenceService: 返回查询结果 + opt 查询出错 + EvidenceService-->>调用者: 报错并退出 + end + EvidenceService-->>调用者: 返回成功 + + +---- + +9. addSignatureAndLogByHash / addSignatureAndLogByCustomKey +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.addSignatureAndLogByHash / addSignatureAndLogByCustomKey + 接口定义:ResponseData addSignatureAndLogByHash(String hashValueSupplement(仅在customKey中用到), String hashValue / customKey, String log, WeIdPrivateKey weIdPrivateKey) + 接口描述:为一个**已经在链上存在的存证**添加日志条目。有两个接口,一个是以hash值为索引,一个可以接受用户自定义索引(customKey);如果自定义索引不存在,则会使用替补hash作为上链索引,此日志将是永久记录在区块链上,最后在尝试获取存证。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValueSupplement + - String + - N + - + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValue + - String + - N + - + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - log + - String + - Y + - 额外信息 + - 长度不能超过2M,必须为UTF-8 + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - customKey + - String + - Y + - 用户自定索引关键字 + - 长度不能超过2M,必须为UTF-8 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +---- + +10. revoke / unRevoke +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.revoke / unRevoke + 接口定义:ResponseData revoke(Hashable object, WeIdAuthentication weIdAuthentication) + 接口描述: 撤销存证 / 撤销存证-可以取消。 + +**接口入参**\ : + +Hashable java.lang.Object + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - Object + - Hashable object + - N + - 实现了Hashable接口的任意Object + - 当前支持Credential,CredentialWrapper,CredentialPojo + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - + - 用户WeID + * - authenticationMethodId + - String + - Y + - + - method Id + + com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +---- + +11. isRevoked +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.isRevoked + 接口定义:ResponseData isRevoked(EvidenceInfo evidenceInfo, String weId) + 接口描述: 检查该存证是否被该WeID撤销。 + +**接口入参**\ : + +com.webank.weid.protocol.base.EvidenceInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - credentialHash + - String + - 凭证Hash值 + - 是一个66个字节的字符串,以0x开头 + * - signInfo + - Map + - 存证创建者信息 + - 链上允许一个存证存在多个创建者 + +com.webank.weid.protocol.base.EvidenceSignInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - signature + - String + - 存证的签名 + - 以Base64编码的存证签名值 + * - timestamp + - String + - 存证创建时间 + - + * - logs + - List + - 额外信息列表 + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - + - 用户WeID + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +---- + +12. createRawEvidenceWithCustomKey +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.createRawEvidenceWithCustomKey + 接口定义:ResponseData createRawEvidenceWithCustomKey(String hashValue,String signature,String log,Long timestamp,String extraKey,String privateKey) + 接口描述: 创建可定制所有输入的原始存证。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValue + - String + - Y + - 哈希值 + - + * - signature + - String + - 存证的签名 + - 以Base64编码的存证签名值 + * - timestamp + - Long + - 存证创建时间 + - + * - log + - String + - 日志 + - + * - extraKey + - String + - + - + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - + - 用户WeID + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +---- + +13. createRawEvidenceWithSpecificSigner +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.EvidenceService.createRawEvidenceWithSpecificSigner + 接口定义:ResponseData createRawEvidenceWithSpecificSigner(String hashValue,String signature,String log,Long timestamp,String extraKey,String signer, + String privateKey) + 接口描述: 创建原始存证接口,其中所有输入(包括签名者)都可以定制。 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - hashValue + - String + - Y + - 哈希值 + - + * - signature + - String + - 存证的签名 + - 以Base64编码的存证签名值 + * - timestamp + - Long + - 存证创建时间 + - + * - log + - String + - 日志 + - + * - extraKey + - String + - + - + * - signer + - String + - + - + * - privateKey + - String + - 私钥 + - 使用十进制数字表示 + + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - + - 用户WeID + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 成功与否 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CREDENTIAL_EVIDENCE_BASE_ERROR + - 100500 + - Evidence标准错误 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +---- + + +CredentialPojoService +^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. createCredential +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.createCredential + 接口定义: ResponseData createCredential(CreateCredentialPojoArgs args) + 接口描述: 根据传入的claim对象生成Credential。 + +**接口入参**\ : + +com.webank.weid.protocol.request.CreateCredentialPojoArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - cptId + - Integer + - Y + - CPT ID + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - expirationDate + - Long + - Y + - 到期时间 + - + * - claim + - T + - Y + - 创建凭证需要的claim数据,参数类型为泛型,为POJO对象(不同的CPT对应不同的POJO类)。 + - 需要通过build-tool工具根据CPT ID生成对应的jar包, + * - weIdAuthentication + - WeIdAuthentication + - Y + - weId身份信息 + - + * - type + - CredentialType + - N + - 凭证类型enum,默认为Original,可选ZKP类型和Lite类型 + - + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥和weid不匹配 + * - CREDENTIAL_ERROR + - 100400 + - credential处理未知异常 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim非法 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: 04a3e89d-825a-49fe-b8f5-8ccb9f487a52 + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560420878712 + expirationDate: 1560470944120 + claim:(java.util.HashMap) + gender: F + name: zhangsan + age: 22 + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + gender: ibu7f + name: el1w8 + age: ajqkr + created: 1560420878712 + type: Secp256k1 + signatureValue: G7UPiw08P5E9dEcSJEo9zpKu/nsUrpn00xDE+mwDXn9gJEohIlRUX5XTGQB4G1w3yThp6R/2RqjUYkuQTaUXbIU= + type:(java.util.ArrayList) + [0]:VerifiableCredential + errorCode: 0 + errorMessage: success + transactionInfo:null + + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用CreateCredential() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 为claim中的每个字段生成盐值 + CredentialPojoService->>CredentialPojoService: 生成签发日期、生成数字签名 + CredentialPojoService-->>调用者: 返回凭证 + +---- + +2. prepareZkpCredential +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.prepareZkpCredential + 接口定义: ResponseData createCredential(CredentialPojo preCredential, String claimJson, WeIdAuthentication weIdAuthentication) + 接口描述: 此接口仅在使用WeDPR的选择性披露时才需要调用,用于生成一些中间数据。用户根据传入的preCredential,claimJson以及weIdAuthentication生成基于系统CPT 111的credential。 + +**接口入参**\ : + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - claimJson + - String + - Y + - User claim + - 用户填入的claim + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + - 获取weIdDocument异常 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(110); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("id", "d5e68eb5-0417-47b0-b678-5eb86c50bf22"); + claim.put("issuer", "did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + claim.put("expirationDate", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + claim.put("cptId", 2000003); + claim.put(issuanceDate, System.currentTimeMillis()); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + CredentialPojo credential = response.getResult; + Map userClaim = new HashMap(); + userClaim.put("name", "zhangsan"); + userClaim.put("age", 18); + userClaim.put("gender", "F"); + String claimJson = DataToolUtils.serialize(userClaim); + + WeIdAuthentication userAuth = new WeIdAuthentication(); + userAuth.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey userPrivateKey = new WeIdPrivateKey(); + userPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + userAuth.setWeIdPrivateKey(userPrivateKey); + + userAuth.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + ResponseData prepareZkpResponse = credentialPojoService.prepareZkpCredential(credential, claimJson, userAuth); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: 04a3e89d-825a-49fe-b8f5-8ccb9f487a52 + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560420878712 + expirationDate: 1560470944120 + claim:(java.util.HashMap) + cptId: 2000003 + credentialSignatureRequest: YWjF2cFZnPT0SKAomEiRkNWU2OGViNS0wNDE3LTQ3YjAtYjY3OC01ZWI4NmM1MGJmMj + userNonce: mNXpIM2lJaUh2STNtc3hvTHgxMHQxZz09Egg1ZTU2MjBmMhpICixsS2NSNWx + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + cptId: ibu7f + credentialSignatureRequest: el1w8 + userNonce: ajqkr + created: 1560420878712 + type: Secp256k1 + signatureValue: G7UPiw08P5E9dEcSJEo9zpKu/nsUrpn00xDE+mwDXn9gJEohIlRUX5XTGQB4G1w3yThp6R/2RqjUYkuQTaUXbIU= + type:(java.util.ArrayList) + [0]:VerifiableCredential + errorCode: 0 + errorMessage: success + transactionInfo:null + + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: prepareZkpCredential() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 为claim中的每个字段生成盐值 + CredentialPojoService->>CredentialPojoService: 生成签发日期、生成数字签名 + CredentialPojoService-->>调用者: 返回凭证 + +---- + +3. createSelectiveCredential +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.createSelectiveCredential + 接口定义: ResponseData createSelectiveCredential(CredentialPojo credentialPojo, ClaimPolicy claimPolicy) + 接口描述: 通过原始凭证和披露策略,创建选择性披露的Credential。 + +.. note:; + + ClaimPolicy内部对选择性披露的策略定义在fieldsToBeDisclosed。它是一个Json字符串,和Claim中定义的Key完全对应,Value为1则为披露(在生成的凭证中显示为原文),Value为0则为不披露(显示为加盐的hash值)。如您的Claim包括name、gender、age三项,想披露name和age,不披露gender,则对应的ClaimPolicy为"{\"name\":1,\"gender\":0,\"age\":1}" + +.. note:: + + 注意:对于已经创建好的选择性披露凭证,不允许再次进行选择性披露。 + +**接口入参**\ : + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.ClaimPolicy + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - fieldsToBeDisclosed + - String + - Y + - 披露配置 + - 根据claim匹配的结构,为一个Json字符串,和Claim字段格式匹配。详见调用示例 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_CLAIM_POLICY_NOT_EXIST + - 100420 + - 披露策略为null + * - CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL + - 100423 + - policy披露信息非法 + * - CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM + - 100427 + - 披露策略与Claim不匹配 + * - CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL + - 100428 + - 披露数据格式错误 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - CREDENTIAL_NOT_SUPPORT_SELECTIVE_DISCLOSURE + - 100440 + - lite credential不支持选择性披露 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs + .setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs + .setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey( + "60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication + .setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + + // 选择性披露 + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1}"); + ResponseData selectiveResponse = + credentialPojoService.createSelectiveCredential(response.getResult(), claimPolicy); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: c4f8ca00-7c1b-4ba0-993f-008106075d9c + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560420975268 + expirationDate: 1560471040676 + claim:(java.util.HashMap) + gender: 0x0756ccf78a0ebd5bd186b054376f1e9d86139bf04f660e9171a74673e5a21c75 + name: zhangsan + age: 22 + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + gender: 0 + name: rr3g0 + age: 9ysgr + created: 1560420975268 + type: Secp256k1 + signatureValue: GxVcZJFEnC7w+ZKOZAjmKy5JfFxoEFqffmCMvbUnVYmzEVKIUtDCiDmokZ2X3jIV/uFvUHQ4DWXksrD6Opr1vLo= + type:(java.util.ArrayList) + [0]:VerifiableCredential + errorCode: 0 + errorMessage: success + transactionInfo:null + + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用createSelectiveCredential(),传入原始凭证 + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 根据claimPolicy来隐藏不披露的字段 + CredentialPojoService->>CredentialPojoService: 生成签发日期、生成数字签名 + CredentialPojoService-->>调用者: 返回凭证 + + +---- + +4. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.verify + 接口定义: ResponseData verify(String issuerWeId, CredentialPojo credential) + 接口描述: 验证credential。 + +**接口入参**\ : + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - issuerWeId + - String + - Y + - WeIdentity DID + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + - 获取weIdDocument异常 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + ResponseData responseVerify = credentialPojoService.verify("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + participant CptService + participant WeIdService + participant 区块链节点 + 调用者->>CredentialPojoService: 调用verify() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>WeIdService: 查询WeIdentity DID存在性 + WeIdService->>区块链节点: 调用智能合约,查询WeIdentity DID属性 + 区块链节点-->>WeIdService: 返回查询结果 + WeIdService-->>CredentialPojoService: 返回查询结果 + opt 查询不存在 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CptService: 查询CPT存在性及Claim关联语义 + CptService->>区块链节点: 调用智能合约,查询CPT + 区块链节点-->>CptService: 返回查询结果 + CptService-->>CredentialPojoService: 返回查询结果 + opt 不符合CPT格式要求 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CredentialPojoService: 验证过期、撤销与否 + opt 任一验证失败 + CredentialPojoService-->>调用者: 报错并退出 + end + opt 未提供验签公钥 + CredentialPojoService->>WeIdService: 查询Issuer对应公钥 + WeIdService->>区块链节点: 调用智能合约,查询Issuer的WeIdentity DID Document + 区块链节点-->>WeIdService: 返回查询结果 + WeIdService-->>CredentialPojoService: 返回查询结果 + end + CredentialPojoService->>CredentialPojoService: 通过公钥与签名对比,验证Issuer是否签发此凭证 + opt 验证签名失败 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService-->>调用者: 返回成功 + +---- + +5. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.verify + 接口定义: ResponseData verify(WeIdPublicKey issuerPublicKey, CredentialPojo credential) + 接口描述: 使用指定公钥验证credential。 + +**接口入参**\ : + +com.webank.weid.protocol.base.WeIdPublicKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 公钥 + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - 获取weIdDocument异常 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_PUBLIC_KEY_NOT_EXISTS + - 100421 + - 公钥不存在 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey("9202079291855274840499629257327649367489192973501473466426182121217769706994308329953406897395674428921435762028726727399019951049448689033610431403383875"); + + ResponseData responseVerify = credentialPojoService.verify(weIdPublicKey, response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + participant CptService + participant 区块链节点 + 调用者->>CredentialPojoService: 调用verify() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CptService: 查询CPT存在性及Claim关联语义 + CptService->>区块链节点: 调用智能合约,查询CPT + 区块链节点-->>CptService: 返回查询结果 + CptService-->>CredentialPojoService: 返回查询结果 + opt 不符合CPT格式要求 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CredentialPojoService: 验证过期、撤销与否 + opt 任一验证失败 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CredentialPojoService: 通过公钥与签名对比,验证Issuer是否签发此凭证 + opt 验证签名失败 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService-->>调用者: 返回成功 + +---- + +6. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.verify + 接口定义: ResponseData verify(String presenterWeId, PresentationPolicyE presentationPolicyE, Challenge challenge, PresentationE presentationE) + 接口描述: 验证Presentation。 + +**接口入参**\ : + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - presenterWeId + - String + - Y + - WeIdentity DID + - 用户的WeIdentity DID + + +com.webank.weid.protocol.base.PresentationPolicyE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - id + - Integer + - Y + - polcyId + - 策略编号 + * - orgId + - String + - Y + - 机构编号 + - + * - version + - Integer + - Y + - 版本 + - + * - policyPublisherWeId + - String + - Y + - WeIdentity DID + - 创建policy机构的WeIdentity DID + * - policy + - Map + - Y + - 策略配置 + - key: CPTID, value: 披露策略对象 + * - extra + - Map + - N + - 扩展字段 + - + + +com.webank.weid.protocol.base.Challenge + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - N + - WeIdentity DID + - policy提供给指定的WeIdentity DID + * - version + - Integer + - Y + - 版本 + - + * - nonce + - String + - Y + - 随机字符串 + - + + +com.webank.weid.protocol.base.PresentationE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - List + - Y + - 上下文 + - + * - type + - List + - Y + - Presentation Type + - + * - credentialList + - List + - Y + - 凭证列表 + - + * - proof + - Map + - Y + - Presentation的签名信息 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - 获取weIdDocument异常 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_SIGNATURE_NOT_EXISTS + - 100422 + * - CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL + - 100423 + - policy披露信息非法 + * - CREDENTIAL_DISCLOSUREVALUE_NOTMATCH_SALTVALUE + - 100424 + - Credential披露信息跟盐信息不一致 + * - CREDENTIAL_CPTID_NOTMATCH + - 100425 + - CPT不匹配 + - 签名不存在 + * - CREDENTIAL_PRESENTERWEID_NOTMATCH + - 100426 + - presenterWeId跟challenge不匹配 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - CREDENTIAL_USE_VERIFY_FUNCTION_ERROR + - 100439 + - 使用了错误的verify方法 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - PRESENTATION_CHALLENGE_NONCE_MISMATCH + - 100605 + - challenge随机数不匹配 + * - PRESENTATION_SIGNATURE_MISMATCH + - 100606 + - presentation验签失败 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationERes = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + //验证Presentation + ResponseData verifyRes = credentialPojoService.verify("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", presentationPolicyE, challenge, presentationERes.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + participant CptService + participant 区块链节点 + 调用者->>CredentialPojoService: 调用verify() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + loop 遍历credentialPojo列表 + CredentialPojoService->>CredentialPojoService: 验证policy和claim里的key是否一致 + opt 任一验证失败 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CptService: 查询CPT存在性及Claim关联语义 + CptService->>区块链节点: 调用智能合约,查询CPT + 区块链节点-->>CptService: 返回查询结果 + CptService-->>CredentialPojoService: 返回查询结果 + opt 不符合CPT格式要求 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CredentialPojoService: 验证过期、撤销与否 + opt 任一验证失败 + CredentialPojoService-->>调用者: 报错并退出 + end + CredentialPojoService->>CredentialPojoService: 通过公钥与签名对比,验证Issuer是否签发此凭证 + opt 验证签名失败 + CredentialPojoService-->>调用者: 报错并退出 + end + end + CredentialPojoService-->>调用者: 返回成功 + +---- + +7. verifyPresentationFromPdf +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.verifyPresentationFromPdf + 接口定义: ResponseData verifyPresentationFromPdf(String pdfTemplatePath, byte[] serializePdf, String presenterWeId, PresentationPolicyE presentationPolicyE, Challenge challenge, PresentationE presentationE) + 接口描述: 验证由PDF Transportation传输的Presentation。 + +**接口入参**\ : + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - pdfTemplatePath + - String + - Y + - PDF模板路径 + - 用于PDF序列化的PDF模板路径 + +java.lang.byte + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - serializePdf + - byte[] + - Y + - 包含PDF数据的byte数组 + - 序列化生成包含PDF数据的byte数组 + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - presenterWeId + - String + - Y + - WeIdentity DID + - 用户的WeIdentity DID + + +com.webank.weid.protocol.base.PresentationPolicyE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - id + - Integer + - Y + - polcyId + - 策略编号 + * - orgId + - String + - Y + - 机构编号 + - + * - version + - Integer + - Y + - 版本 + - + * - policyPublisherWeId + - String + - Y + - WeIdentity DID + - 创建policy机构的WeIdentity DID + * - policy + - Map + - Y + - 策略配置 + - key: CPTID, value: 披露策略对象 + * - extra + - Map + - N + - 扩展字段 + - + + +com.webank.weid.protocol.base.Challenge + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - N + - WeIdentity DID + - policy提供给指定的WeIdentity DID + * - version + - Integer + - Y + - 版本 + - + * - nonce + - String + - Y + - 随机字符串 + - + + +com.webank.weid.protocol.base.PresentationE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - List + - Y + - 上下文 + - + * - type + - List + - Y + - Presentation Type + - + * - credentialList + - List + - Y + - 凭证列表 + - + * - proof + - Map + - Y + - Presentation的签名信息 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - 获取weIdDocument异常 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_SIGNATURE_NOT_EXISTS + - 100422 + * - CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL + - 100423 + - policy披露信息非法 + * - CREDENTIAL_DISCLOSUREVALUE_NOTMATCH_SALTVALUE + - 100424 + - Credential披露信息跟盐信息不一致 + * - CREDENTIAL_CPTID_NOTMATCH + - 100425 + - CPT不匹配 + - 签名不存在 + * - CREDENTIAL_PRESENTERWEID_NOTMATCH + - 100426 + - presenterWeId跟challenge不匹配 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - PRESENTATION_CHALLENGE_NONCE_MISMATCH + - 100605 + - challenge随机数不匹配 + * - PRESENTATION_SIGNATURE_MISMATCH + - 100606 + - presentation验签失败 + * - TRANSPORTATION_PDF_VERIFY_ERROR + - 100809 + - PDF验证失败 + + +**调用示例** + +.. code-block:: java + + //序列化presentation,生成包含PDF信息的byte数组 + ResponseData retSerialize = TransportationFactory.newPdfTransportation() + .serializeWithTemplate( + presentationE1, + new ProtocolProperty(EncodeType.ORIGINAL), + "src/test/resources/test-template.pdf"); + + //反序列化包含PDF信息的byte数组为Presentation + ResponseData retDeserialize = TransportationFactory.newPdfTransportation() + .deserialize( + retSerialize.getResult(), + PresentationE.class, + weIdAuthentication); + + //验证presentation + ResponseData response = credentialPojoService.verifyPresentationFromPdf( + "src/test/resources/test-template.pdf", + retSerialize.getResult(), + credentialPojoNew1.getIssuer(), + presentationPolicyE1, + challenge1, + retDeserialize.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +8. createPresentation +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.createPresentation + 接口定义: ResponseData createPresentation(List credentialList, PresentationPolicyE presentationPolicyE, Challenge challenge, WeIdAuthentication weIdAuthentication) + 接口描述: 创建Presentation。 + +**接口入参**\ : + + +java.uitl.List + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.PresentationPolicyE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - id + - Integer + - Y + - polcyId + - 策略编号 + * - orgId + - String + - Y + - 机构编号 + - + * - version + - Integer + - Y + - 版本 + - + * - policyPublisherWeId + - String + - Y + - WeIdentity DID + - 创建policy机构的WeIdentity DID + * - policy + - Map + - Y + - 策略配置 + - key: CPTID, value: 披露策略对象 + * - extra + - Map + - N + - 扩展字段 + - + + +com.webank.weid.protocol.base.Challenge + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - N + - WeIdentity DID + - policy提供给指定的WeIdentity DID + * - version + - Integer + - Y + - 版本 + - + * - nonce + - String + - Y + - 随机字符串 + - + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - Y + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - PresentationE + - 创建的Presentation + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.PresentationE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - List + - 上下文 + - + * - type + - List + - Presentation Type + - + * - credentialList + - List + - 凭证列表 + - + * - proof + - Map + - Presentation的签名信息 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 用户weId不匹配其私钥 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_CLAIM_POLICY_NOT_EXIST + - 100420 + - 披露策略为null + * - CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM + - 100427 + - 披露策略与Claim不匹配 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - PRESENTATION_CHALLENGE_INVALID + - 100600 + - challenge无效 + * - PRESENTATION_CHALLENGE_WEID_MISMATCH + - 100601 + - challenge中的weId不匹配用户的weId + * - PRESENTATION_POLICY_INVALID + - 100602 + - policy无效 + * - PRESENTATION_CREDENTIALLIST_MISMATCH_CLAIM_POLICY + - 100603 + - credentialList不匹配Policy + * - PRESENTATION_WEID_PUBLICKEY_ID_INVALID + - 100604 + - 公钥编号无效 + * - PRESENTATION_POLICY_PUBLISHER_WEID_INVALID + - 100609 + - policy中的publisherWeId无效 + * - PRESENTATION_POLICY_PUBLISHER_WEID_NOT_EXIST + - 100610 + - policy中的publisherWeId不存在 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + List credentialList = new ArrayList(); + credentialList.add(response.getResult()); + + //创建Challenge + Challenge challenge = Challenge.create("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", String.valueOf(System.currentTimeMillis())); + + //创建PresentationPolicyE + String policyJson = "{\"extra\" : {\"extra1\" : \"\",\"extra2\" : \"\"},\"id\" : 123456,\"version\" : 1,\"orgId\" : \"webank\",\"weId\" : \"did:weid:1000:0x0231765e19955fc65133ec8591d73e9136306cd0\",\"policy\" : {\"1017\" : {\"fieldsToBeDisclosed\" : {\"gender\" : 0,\"name\" : 1,\"age\" : 0}}}}"; + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromJson(policyJson); + + //创建Presentation + ResponseData presentationE = credentialPojoService.createPresentation(credentialList, presentationPolicyE, challenge, weIdAuthentication); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.PresentationE) + context:(java.util.ArrayList) + [0]:https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + type:(java.util.ArrayList) + [0]:VerifiablePresentation + verifiableCredential:(java.util.ArrayList) + [0]:com.webank.weid.protocol.base.CredentialPojo + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: 67598cc5-a922-4e9f-ae0a-90c6285a8236 + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560425696276 + expirationDate: 1560475761684 + claim:(java.util.HashMap) + gender: 0x8dba4ce05ca123e0c48b877f461e1b8c362fcab9d03330dcb80d7d039081f50b + name: zhangsan + age: 0xdeb5a47d7ab03d9fefe2169cc59db146cec6f24005bcf0b2e2a0c95bfe7adde5 + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + gender: 0 + name: yjckg + age: 0 + created: 1560425696276 + type: Secp256k1 + signatureValue: HCgmoX0f7ZYkwpd+pJ2+RCRKNt5lf9nbl8g9YWTSuA32IIoRSjMr7GPZVbe5bcu+hD/pnkAJbbinJo4/YqOOync= + type:(java.util.ArrayList) + [0]:VerifiableCredential + proof:(java.util.HashMap) + created: 1560425696412 + type: Secp256k1 + verificationMethod: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + nonce: DJulONVxD2TFidB8vaYH + signatureValue: G8ivS1e625NT8qSzLEugbqkRW6HDJNA4Lfcl7uCXV+uEffPMVF6Bwnk0pyCOd+4bbw90pMaj+EVxeL79acYPzM4= + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用verify() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + loop 遍历credentialPojo列表 + CredentialPojoService->>CredentialPojoService: 根据credentialPojo中的cptId获取对应的claimPolicy + opt claimPolicy + CredentialPojoService-->>调用者: continue + end + CredentialPojoService->>CredentialPojoService: 根据claimPolicy,调用createSelectiveCredential()方法,做选择性披露 + opt 选择性披露失败 + CredentialPojoService-->>调用者: 失败退出 + end + end + CredentialPojoService->>CredentialPojoService: 设置context等元数据属性 + CredentialPojoService->>CredentialPojoService: 对presentation整体签名,放入proof结构,同时设置其他proof属性,用于验证 + CredentialPojoService-->>调用者: 返回成功 + +---- + + +9. getCredentialPojoHash +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.getCredentialPojoHash + 接口定义:ResponseData getCredentialHash(CredentialPojo args) + 接口描述: 传入CredentialPojo信息生成CredentialPojo整体的Hash值,一般在生成Evidence时调用。 + +**接口入参**\ : com.webank.weid.protocol.base.CredentialPojo + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + //创建CredentialPojo + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + ResponseData resp = credentialPojoService.getCredentialPojoHash(response.getResult()); + +.. code-block:: text + + 返回结果如: + result: 0x06173e4b714d57565ae5ddf23c4e84cb0a9824cb72eab476303d2dd1cc0a4728 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用GetCredentialPojoHash() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 生成凭证Hash + CredentialPojoService-->>调用者: 返回凭证Hash + +---- + +10. addSignature +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.addSignature + 接口定义:ResponseData addSignature(List credentialList, WeIdPrivateKey weIdPrivateKey) + 接口描述:多签,在原凭证列表的基础上,创建包裹成一个新的多签凭证,由传入的私钥所签名。此凭证的CPT为一个固定值。在验证一个多签凭证时,会迭代验证其包裹的所有子凭证。本接口不支持创建选择性披露的多签凭证。 + +**接口入参**\ : java.util.ArrayList + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Credential + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.response.TransactionInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - blockNumber + - BigInteger + - 交易块高 + - + * - transactionHash + - String + - 交易hash + - + * - transactionIndex + - BigInteger + - 交易索引 + - + + +com.webank.weid.protocol.base.Credential + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - 默认为106 + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - JsonSchema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialPojoArgs createCredentialPojoArgs = new CreateCredentialPojoArgs(); + createCredentialPojoArgs.setClaim(claim); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setExpirationDate(1551448312461L); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialPojoArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = credentialPojoService.createCredentialPojo(createCredentialArgs); + List credList = new ArrayList<>(); + credList.add(response.getResult().getCredentialPojo()); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialPojoArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialPojoArgs.setExpirationDate(expirationDate); + CredentialPojo tempCredential = + credentialPojoService.createCredentialPojo(createCredentialPojoArgs).getResult().getCredentialPojo(); + credentialList.add(tempCredential); + ResponseData multiSignedResp = credentialService.addSignature(credList, weIdPrivateKey); + System.out.println(multiSignedResp); + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + credentialPojo:(com.webank.weid.protocol.base.CredentialPojo) { + { + "claim": { + "credentialList": [ + { + "claim": { + "age": 1, + "gender": "F", + "id": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33", + "name": "1" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000087, + "expirationDate": 1567491752, + "id": "6ea6e209-10e9-4a93-b6be-12af1a32655b", + "issuanceDate": 1567405352, + "issuer": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33", + "proof": { + "created": 1567405352, + "creator": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33#keys-0", + "salt": { + "age": "yOwN7", + "gender": "jjB85", + "id": "BmRYI", + "name": "BjYqF" + }, + "signatureValue": "G+SNG3rBZNDvRNgRtJugPtX1FmE8XJIkV4CGPK\/nt\/breIPMJ5wYxImTp2QAxBUe5HMwCe9PPGhhMJJAazM5u9k=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + }, + { + "claim": { + "age": 1, + "gender": "F", + "id": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53", + "name": "1" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000087, + "expirationDate": 1567491842, + "id": "a3544a9c-6cb6-4688-9622-bb935fb0d93f", + "issuanceDate": 1567405355, + "issuer": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53", + "proof": { + "created": 1567405355, + "creator": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53#keys-0", + "salt": { + "age": "5nImi", + "gender": "Me224", + "id": "5pYs2", + "name": "z6VmW" + }, + "signatureValue": "HC8OAG\/dRmteGSIGWIDekp8fC1KJI8EEDZBb29HiTLXvVj350l9yTOHeGSBCr2VRY\/DSHT5ONjlvcrO4Mqa3Auo=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + } + ] + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 107, + "expirationDate": 1567491842, + "id": "ad5d5a54-4574-4b3b-b1df-9d0687b6a0ac", + "issuanceDate": 1567405359, + "issuer": "did:weid:1000:1:0x4e9a111867ed6370e1e23f7a79426f6649eb78c6", + "proof": { + "created": 1567405359, + "creator": "did:weid:1000:1:0x4e9a111867ed6370e1e23f7a79426f6649eb78c6#keys-0", + "salt": { + "credentialList": "" + }, + "signatureValue": "HC1y3rfyb\/2sg+E2Uulczm8VDtmQ6VrU\/9ow4e4nP3lVUOv4Gz41pfBrJHnV4wQoUbQsCYpezFx5sdaUwUILV1I=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + } + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用addSignature() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 生成签发日期、以原凭证列表为Claim生成数字签名 + CredentialPojoService-->>调用者: 返回凭证 + +---- + +11. createTrustedTimestamp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.createTrustedTimestamp + 接口定义:ResponseData createTrustedTimestamp(List credentialList, WeIdAuthentication weIdAuthentication) + 接口描述: 使用第三方可信时间戳服务,创建一个可信时间戳凭证。 + +.. note:: + 注意:本服务需要您先行配置好时间戳服务的相关参数,请参见\ `时间戳服务配置步骤 `__\ 。当前,可信时间戳服务支持使用WeSign(微鉴证)集成。 + +.. note:: + 注意:创建可信时间戳凭证的输入参数是一个凭证list。当前,因为一些技术限制,还不支持对**已经选择性披露的凭证**进行可信时间戳的创建。也就是说,如果您传入的凭证list里面有任何一个凭证是选择性披露的,那么创建将会失败。 + +.. note:: + 注意:对于已经创建好的可信时间戳凭证,您可以通过调用createSelectiveCredential对其进行选择性披露。 + +**接口入参**\ : java.util.ArrayList + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - Y + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Credential + - + - 见下 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - 版本 + - 默认为v1 + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - 默认为106 + * - issuer + - String + - Y + - WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - JsonSchema无效 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_PRIVATE_KEY_NOT_EXISTS + - 100415 + - 私钥为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - TIMESTAMP_SERVICE_BASE_ERROR + - 100433 + - 时间戳服务一般错误,请参照log检查具体错误 + * - CREDENTIAL_SYSTEM_CPT_CLAIM_VERIFY_ERROR + - 100434 + - 凭证签名验证通过,但是内部系统CPT内容验证失败 + * - TIMESTAMP_SERVICE_UNCONFIGURED + - 100435 + - 时间戳服务未配置 + * - TIMESTAMP_SERVICE_WESIGN_ERROR + - 100436 + - 时间戳服务微鉴证侧出错,请参照log检查具体错误 + * - TIMESTAMP_VERIFICATION_FAILED + - 100437 + - 时间戳验证不通过(可能是hash值/时间/时间戳签名任一错误) + * - TIMESTAMP_CREATION_FAILED_FOR_SELECTIVELY_DISCLOSED + - 100438 + - 时间戳服务不支持对已经选择性披露的凭证进行创建时间戳 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + + HashMap claim = new HashMap(3); + claim.put("name", "zhang san"); + claim.put("gender", "F"); + claim.put("age", 18); + + CreateCredentialPojoArgs createCredentialPojoArgs = new CreateCredentialPojoArgs(); + createCredentialPojoArgs.setClaim(claim); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setExpirationDate(1551448312461L); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + createCredentialPojoArgs.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = credentialPojoService.createCredentialPojo(createCredentialArgs); + List credList = new ArrayList<>(); + credList.add(response.getResult().getCredentialPojo()); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialPojoArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialPojoArgs.setExpirationDate(expirationDate); + CredentialPojo tempCredential = + credentialPojoService.createCredentialPojo(createCredentialPojoArgs).getResult().getCredentialPojo(); + credentialList.add(tempCredential); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + ResponseData trustedCred = credentialService.createTrustedTimestamp(credList, weIdAuthentication); + System.out.println(trustedCred); + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + credentialPojo:(com.webank.weid.protocol.base.CredentialPojo) { + { + "claim": { + "credentialList": [ + { + "claim": { + "age": 1, + "gender": "F", + "id": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33", + "name": "1" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000087, + "expirationDate": 1567491752, + "id": "6ea6e209-10e9-4a93-b6be-12af1a32655b", + "issuanceDate": 1567405352, + "issuer": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33", + "proof": { + "created": 1567405352, + "creator": "did:weid:1000:1:0xa4c2666560499868baf1906941f806b6d1c26e33#keys-0", + "salt": { + "age": "yOwN7", + "gender": "jjB85", + "id": "BmRYI", + "name": "BjYqF" + }, + "signatureValue": "G+SNG3rBZNDvRNgRtJugPtX1FmE8XJIkV4CGPK\/nt\/breIPMJ5wYxImTp2QAxBUe5HMwCe9PPGhhMJJAazM5u9k=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + }, + { + "claim": { + "age": 1, + "gender": "F", + "id": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53", + "name": "1" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 2000087, + "expirationDate": 1567491842, + "id": "a3544a9c-6cb6-4688-9622-bb935fb0d93f", + "issuanceDate": 1567405355, + "issuer": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53", + "proof": { + "created": 1567405355, + "creator": "did:weid:1000:1:0x309320a01f215a380c6950e80a89181ad8a8cd53#keys-0", + "salt": { + "age": "5nImi", + "gender": "Me224", + "id": "5pYs2", + "name": "z6VmW" + }, + "signatureValue": "HC8OAG\/dRmteGSIGWIDekp8fC1KJI8EEDZBb29HiTLXvVj350l9yTOHeGSBCr2VRY\/DSHT5ONjlvcrO4Mqa3Auo=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + } + ] + "timestampAuthority": "wesign", + "authoritySignature": "MhmbHC1y3rfyb\/2sg+E2Uulczm8VDtmQ6VrU\/9ow4e4nP3lVUOv4Gz41pfBrJHnV4wQoUbQsCYpezFx5sdaUwUILV1I=HC1y3rfyb\/2sg+E2Uulczm8VDtmQ6VrU\/9ow4e4nP3lVUOv4Gz41pfBrJHnV4wQoUbQsCYpezFx5sdaUwUILV1I=HC1y3rfyb\/2sg+E2Uulczm8VDtmQ6VrU\/9ow4e4nP3lVUOv4Gz41pfBrJHnV4wQoUbQsCYpezFx5sdaUwUILV1I=a235==", + "timestamp": 151233113000, + "claimHash": "0xe3f48648beee61d17de609d32af36ac0bf4d68a9352890b04d53841c4949bd13" + }, + "context": "https:\/\/github.com\/WeBankFinTech\/WeIdentity\/blob\/master\/context\/v1", + "cptId": 108, + "expirationDate": 1567491842, + "id": "ad5d5a54-4574-4b3b-b1df-9d0687b6a0ac", + "issuanceDate": 1567405359, + "issuer": "did:weid:1000:1:0x4e9a111867ed6370e1e23f7a79426f6649eb78c6", + "proof": { + "created": 1567405359, + "creator": "did:weid:1000:1:0x4e9a111867ed6370e1e23f7a79426f6649eb78c6#keys-0", + "salt": { + "credentialList": "" + }, + "signatureValue": "HC1y3rfyb\/2sg+E2Uulczm8VDtmQ6VrU\/9ow4e4nP3lVUOv4Gz41pfBrJHnV4wQoUbQsCYpezFx5sdaUwUILV1I=", + "type": "Secp256k1" + }, + "type": [ + "VerifiableCredential" + ] + } + errorCode: 0 + errorMessage: success + transactionInfo:null + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用createTrustedTimestamp() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 生成全部不披露的凭证并生成hash + CredentialPojoService->>时间戳服务: 发送hash,生成时间戳 + 时间戳服务-->>CredentialPojoService: 返回时间戳 + CredentialPojoService->>CredentialPojoService: 生成时间戳凭证 + CredentialPojoService-->>调用者: 返回凭证 + + +---- + +12. createDataAuthToken +~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.createDataAuthToken + 接口定义:ResponseData createCredential(Cpt101 authInfo, WeIdAuthentication weIdAuthentication) + 接口描述: 根据传入的授权要求信息,生成符合CPT101格式规范的数据授权凭证。该凭证需要被verify之后和Endpoint Service结合使用。 + +..note:: + + 注意:使用这个接口的前提是首先需要将CPT 101注册到链上。如果您是新搭了一条WeIdentity 1.6.0+的链,那么搭链过程中这一步已经自动完成了。否则(如您是升级SDK),您需要使用部署WeIdentity合约的私钥(ecdsa_key)去将CPT 101注册到链上。下文的代码范例中我们给出了详细的流程 + +**接口入参**\ : + +com.webank.weid.protocol.cpt.Cpt101 + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - fromWeId + - String + - Y + - 发起授权的WeIdentity DID(必须同时是Issuer) + - 必须在链上存在,且需要传入私钥作为Issuer + * - toWeId + - String + - Y + - 接受授权的WeIdentity DID + - 必须在链上存在且和fromWeId不同 + * - serviceUrl + - String + - Y + - 所授权内容在Endpoint Service上注册的service URL + - 必须是一个包含主机名,端口号,以及端点地址的标准URL + * - resourceId + - String + - Y + - UUID + - 用于标识资源的符合UUID格式字符串 + * - duration + - Long + - Y + - 授权有效时间 + - 同时决定了凭证的expirationDate + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - 必须和fromWeId一致 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,必须和fromWeId在链上所公开的某个公钥一致 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥和weid不匹配 + * - CREDENTIAL_ERROR + - 100400 + - credential处理未知异常 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim非法 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - AUTHORIZATION_FROM_TO_MUST_BE_DIFFERENT + - 100450 + - fromWeId和toWeId必须不同 + * - AUTHORIZATION_CANNOT_AUTHORIZE_OTHER_WEID_RESOURCE + - 100451 + - fromWeId必须和Issuer相同 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + +**调用示例** + +.. code-block:: java + + // Enforce a Register/Update system CPT first + WeIdAuthentication sdkAuthen = new WeIdAuthentication(); + ECKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate(privateKey); + String keyWeId = WeIdUtils + .convertAddressToWeId(new Address(Keys.getAddress(keyPair)).toString()); + sdkAuthen.setWeId(keyWeId); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + sdkAuthen.setWeIdPrivateKey(weIdPrivateKey); + if (!weIdService.isWeIdExist(keyWeId).getResult()) { + CreateWeIdArgs wargs = new CreateWeIdArgs(); + wargs.setWeIdPrivateKey(weIdPrivateKey); + wargs.setPublicKey(keyPair.getPublicKey().toString(10)); + weIdService.createWeId(wargs); + } + String cptJsonSchema = DataToolUtils + .generateDefaultCptJsonSchema(Class.forName("com.webank.weid.protocol.cpt.Cpt101")); + CptStringArgs args = new CptStringArgs(); + args.setCptJsonSchema(cptJsonSchema); + args.setWeIdAuthentication(sdkAuthen); + if (cptService.queryCpt(CredentialConstant.AUTHORIZATION_CPT).getResult() == null) { + cptService.registerCpt(args, CredentialConstant.AUTHORIZATION_CPT); + } else { + cptService.updateCpt(args, CredentialConstant.AUTHORIZATION_CPT); + } + + // Init params + Cpt101 authInfo = new Cpt101(); + authInfo.setFromWeId(createWeIdResultWithSetAttr.getWeId()); + String toWeId = this.createWeIdWithSetAttr().getWeId(); + authInfo.setToWeId(toWeId); + authInfo.setDuration(360000L); + authInfo.setResourceId(UUID.randomUUID().toString()); + authInfo.setServiceUrl("http://127.0.0.1:6011/fetch-data"); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResultWithSetAttr.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + weIdAuthentication.setWeIdPublicKeyId(createWeIdResultWithSetAttr.getWeId() + "#keys-0"); + + // Create and check + ResponseData authTokenCredResp = credentialPojoService + .createDataAuthToken(authInfo, weIdAuthentication); + System.out.println(DataToolUtils.deserialize(authTokenCredResp.getResult())); + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + { + "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/WeBankFinTech/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"] + } + errorCode: 0 + errorMessage: success + transactionInfo:null + + + +**时序图** + +.. mermaid:: + + sequenceDiagram + participant 调用者 + participant CredentialPojoService + 调用者->>CredentialPojoService: 调用createDataAuthToken() + CredentialPojoService->>CredentialPojoService: 入参非空、格式及合法性检查 + opt 入参校验失败 + CredentialPojoService-->>调用者: 报错,提示参数不合法并退出 + end + CredentialPojoService->>CredentialPojoService: 组装符合格式的CPT101的Claim + CredentialPojoService->>CredentialPojoService: 生成签发日期、生成数字签名 + CredentialPojoService-->>调用者: 返回数据授权凭证 + +13. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.verify + 接口定义: ResponseData verify(String issuerWeId, String weIdPublicKeyId, CredentialPojo credential) + 接口描述: 通过传入的Issuer的WeID,并指定其链上公钥ID,验证credential。若验证失败,则会遍历所有公钥;如果能够找到一个适配的,那么就返回验证成功但公钥ID不匹配。 + +**接口入参**\ : + +java.lang.String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - issuerWeId + - String + - Y + - WeIdentity DID + - + * - weIdPublicKeyId + - String + - Y + - 公钥ID + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - 交易信息 + - + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + - 获取weIdDocument异常 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - CREDENTIAL_VERIFY_SUCCEEDED_WITH_WRONG_PUBLIC_KEY_ID + - 100442 + - 验证成功,但公钥ID与传入值不同 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialPojoService credentialPojoService = new CredentialPojoServiceImpl(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setWeIdPublicKeyId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialPojoService.createCredential(createCredentialPojoArgs); + + ResponseData responseVerify = credentialPojoService.verify("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7", "0", response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +Persistence +^^^^^^^^^^^^^^^^^ + +1. add +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.add + 接口定义: public ResponseData add(String domain, String id, String data); + 接口描述: 将数据存储到配置的存储库中 + +.. note:: + 注意:数据存储在相应的domain中,目前系统内置domain为7个,如需修改或新增domain,可在weidentity.properties进行自定义配置。 + +.. list-table:: + :header-rows: 1 + + * - domain + - 描述 + * - defaultInfo + - 系统内置默认的domain + * - encryptKey + - 密钥存储的domain,比如transportation中加密的密钥存储 + * - templateSecret + - 零知识量证明流程需要 + * - masterKey + - 零知识量证明流程需要 + * - credentialSignature + - 零知识量证明流程需要 + * - weIdAuth + - weidauth存放鉴权时使用 + * - resourceInfo + - transportation下载模式存储原资源数据用的 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - id + - String + - Y + - 存储数据对应的id + * - data + - String + - Y + - 存储的具体数据 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回结果 + - 添加数据成功为1,不成功为0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id = "123"; + String data = "data123456"; + // 调用persistence.add接口 + ResponseData result = persistence.add(domain, id, data); +---- + +2. batchAdd +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.batchAdd + 接口定义: public ResponseData batchAdd(String domain, Map keyValueList); + 接口描述: 数据批量存储到配置的存储库中 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - keyValueList + - Map + - Y + - 批量数据 + -存储格式为id-value的形式 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回批量添加的数据数量 + - 添加数据成功加1,不成功加0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + * - PERSISTENCE_BATCH_ADD_DATA_MISMATCH + - 100904 + - 存储库批量存储参数不匹配 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id1 = "12345"; + String data1 = "data12345"; + String id2 = "54321"; + String data2 = "data54321"; + //以id-value形式将数据批量存储到HashMap + HashMap map = new HashMap<>(); + map.put(id1, data1); + map.put(id2, data2); + //调用persistence.batchAdd接口实现批量存储 + ResponseData res = persistence.batchAdd("domain.defaultInfo", map); +---- + +3. get +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.get + 接口定义: public ResponseData get(String domain, String id); + 接口描述: 从相关存储库读取数据 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - id + - String + - Y + - 数据的id + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 返回的具体数据 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + * - PERSISTENCE_DATA_EXPIRE + - 160015 + - 存储库数据失效 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id = "12345"; + String data = "data123456"; + // 存储数据 + ResponseData result = persistence.add(domain, id, data); + //通过id读取数据 + ResponseData res = persistence.get(domain, id); +---- + +4. delete +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.delete + 接口定义: public ResponseData delete(String domain, String id); + 接口描述: 从相关存储库中删除数据 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - id + - String + - Y + - 数据的id + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回结果 + - 删除成功返回1,删除失败返回0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id = "123"; + String data = "data123"; + // 存储数据 + ResponseData result = persistence.add(domain, id, data); + //通过id删除相应数据 + ResponseData res = persistence.delete(domain, id); +---- + +5. update +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.update + 接口定义: public ResponseData update(String domain, String id, String data); + 接口描述: 更新存储库中对应的数据 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - id + - String + - Y + - 存储数据对应的id + * - data + - String + - Y + - 更新到存储库的具体数据 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回结果 + - 更新数据成功为1,不成功为0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id = "123456"; + String data = "data123456"; + String data1 = "data12345654321" + //存储数据 + ResponseData result = persistence.add(domain, id, data); + //更新数据 + ResponseData result1 = persistence.update(domain, id, data1); +---- + +6. addOrUpdate +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.addOrUpdate + 接口定义: public ResponseData addOrUpdate(String domain, String id, String data); + 接口描述: 更新或新增数据 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - domain + - String + - Y + - 数据存储的域 + * - id + - String + - Y + - 存储数据对应的id + * - data + - String + - Y + - 新增或更新到存储库的具体数据 + - 根据id查询数据是否存在或者失效,存在且未失效则进行更新 否则进行新增 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回结果 + - 更新或新增数据成功为1,不成功为0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 + * - PERSISTENCE_DATA_EXPIRE + - 160015 + - 存储库数据失效 + +**调用示例** + +.. code-block:: java + + String domain = "domain.defaultInfo"; + String id = "1111"; + String data = "data1111"; + //存储或更新数据,根存储库中是否有对应id来判断调用add或者update接口 + ResponseData result = persistence.addOrUpdate(domain, id, data); +---- + +7. addTransaction +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.suite.persistence.Persistence.addTransaction + 接口定义: public ResponseData addTransaction(TransactionArgs transactionArgs); + 接口描述: 新增交易数据 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - transactionArgs + - TransactionArgs + - Y + - 离线交易相关参数 + - 将离线交易存储到存储库 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - 返回结果 + - 新增离线数据成功为1,不成功为0 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - PRESISTENCE_DATA_KEY_INVALID + - 100901 + - persistence的id不能为空 + * - PRESISTENCE_DOMAIN_ILLEGAL + - 100902 + - domain非法 + * - PRESISTENCE_DOMAIN_INVALID + - 100903 + - domain无效 + * - PERSISTENCE_EXECUTE_FAILED + - 160011 + - mysql存储失败 + * - PERSISTENCE_GET_CONNECTION_ERROR + - 160013 + - 存储库连接池连接失败 +---- + +纯功能接口列表(无存储依赖) +-------- + +WeIdServiceConsole +^^^^^^^^^^^ + +1. createWeIdDocument +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.createWeIdDocument + 接口定义:ResponseData createWeIdDocument(String publicKey) + 接口描述: 外部传入公钥,根据该公钥生成初始的WeIdDocument。 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 公钥十进制字符串 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocument + - + - 见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - WeIdentity DID + - + * - authentication + - List\ :raw-html-m2r:`` + - + - 认证方集合,见下 + * - service + - List\ :raw-html-m2r:`` + - + - 服务端点集合,见下 + + +com.webank.weid.protocol.base.AuthenticationProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - verification method id + * - type + - String + - 类型 + - 默认为:Ed25519VerificationKey2020 + * - controller + - String + - 方法拥有人 + - verification method controller + * - publicKeyMultibase + - String + - 验证公钥 + - 使用base58编码的公钥 + +com.webank.weid.protocol.base.ServiceProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - + * - type + - String + - 类型 + - + * - serviceEndpoint + - String + - 联系/服务方式 + - 邮箱、github个人主页等 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_KEYPAIR_CREATE_FAILED + - 100107 + - 创建密钥对失败 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥和weid不匹配 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + ResponseData response = weIdServiceConsole.createWeIdDocument("13079093397463814932731720163442777403208788175453836227824139092404945067394266611910031425181012754616377192193136435818972874637291518463471522281921222"); + + +.. code-block:: text + + 输出结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + authentication: + [0]: + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + service: + [0]: + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +2. createWeIdDocumentJson +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.createWeIdDocumentJson + 接口定义:ResponseData createWeIdDocumentJson(String publicKey) + 接口描述: 外部传入公钥,根据该公钥生成初始的WeIdDocument的Json序列化结果 + +**接口入参**\ : String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - publicKey + - String + - Y + - 公钥十进制字符串 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - weidDocument Json + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + ResponseData response = weIdServiceConsole.createWeIdDocumentJson("13079093397463814932731720163442777403208788175453836227824139092404945067394266611910031425181012754616377192193136435818972874637291518463471522281921222"); + + +.. code-block:: text + + 返回结果如下: + result: {"@context" : "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", + "id" : "did:weid:101:0xd9aeaa982fc21ea9addaf09e4f0c6a23a08d306a", + "authentication" : [ { + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + } ], + "service" : [ { + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + } ] + } + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +3. getWeIdDocumentMetadata +~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.createWeIdDocumentMetadata + 接口定义:ResponseData createWeIdDocumentMetadata() + 接口描述: 创建WeIdentity DID DocumentMetadata对象。 + +**接口入参**\ : 无 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocumentMetadata + - + - 见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + com.webank.weid.protocol.base.WeIdDocumentMetadata + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - created + - Long + - 创建 + - + * - updated + - Long + - 修改 + - + * - deactivated + - boolean + - 解散 + - + * - versionId + - int + - 版本Id + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_DOES_NOT_EXIST + - 100104 + - WeIdentity DID不存在 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + ResponseData response = weIdServiceConsole.createWeIdDocumentMetadata(); + + +.. code-block:: text + + 返回结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + created: 1686560615 + updated: 1686560615 + deactivated: false + versionId: 1 + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +4. setService +~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.setService + 接口定义:ResponseData setService(WeIdDocument weIdDocument, ServiceArgs setServiceArgs) + 接口描述: 在给定的WeIdDocument中添加Service信息。 + +**接口入参**\ : + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdDocument + - WeIdDocument + - Y + - WeIdentity Document + - + +com.webank.weid.protocol.request.ServiceArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - + * - type + - String + - 类型 + - + * - serviceEndpoint + - String + - 联系/服务方式 + - 邮箱、github个人主页等 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocument + - + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - WEID_SERVICE_TYPE_OVERLIMIT + - 100110 + - type字段超长 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + WeIdDocument weIdDocument= weIdServiceConsole.createWeIdDocument("13079093397463814932731720163442777403208788175453836227824139092404945067394266611910031425181012754616377192193136435818972874637291518463471522281921222"); + + ServiceArgs setServiceArgs = new SetServiceArgs(); + setServiceArgs.setType("drivingCardService"); + setServiceArgs.setServiceEndpoint("https://weidentity.webank.com/endpoint/8377464"); + + ResponseData response = weIdServiceConsole.setService(weIdDocument, serviceArgs); + + +.. code-block:: text + + 返回结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + authentication:(java.util.ArrayList) + [0]:com.webank.weid.protocol.base.AuthenticationProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + service:(java.util.ArrayList) + [0]:com.webank.weid.protocol.base.ServiceProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + [1]:com.webank.weid.protocol.base.ServiceProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#2d37911b + type: drivingCardService + serviceEndpoint: https://weidentity.webank.com/endpoint/xxxxx + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + + +5. setAuthentication +~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.setAuthentication + 接口定义:ResponseData setAuthentication(WeIdDocument weIdDocument, AuthenticationArgs authenticationArgs) + 接口描述: 在给定的WeIdDocument中添加Authentication信息。 + +**接口入参**\ : + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdDocument + - WeIdDocument + - Y + - WeIdentity Document + - + +com.webank.weid.protocol.request.AuthenticationArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - owner + - String + - N + - 所有者 + - 默认为当前WeIdentity DID + * - publicKey + - String + - Y + - 数字公钥 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - WeIdDocument + - + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - 无效的WeIdentity DID + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥格式非法 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥不与WeIdentity DID所对应 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 其他错误 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + WeIdDocument weIdDocument= weIdServiceConsole.createWeIdDocument("13079093397463814932731720163442777403208788175453836227824139092404945067394266611910031425181012754616377192193136435818972874637291518463471522281921222"); + + AuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); + setAuthenticationArgs.setPublicKey( + "13161444623157635919577071263152435729269604287924587017945158373362984739390835280704888860812486081963832887336483721952914804189509503053687001123007342"); + + ResponseData response = weIdServiceConsole.setAuthentication(weIdDocument, setAuthenticationArgs); + + +.. code-block:: text + + 返回结果如下: + result:(com.webank.weid.protocol.base.WeIdDocument) + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + authentication:(java.util.ArrayList) + [0]:com.webank.weid.protocol.base.AuthenticationProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-116cc51b + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: zNT4AwSzTb3qwQXaDeE1tg8e8QYhWLMuguH6yR6XmZBnVtJVbidxCZ6dSd17YNi9z7oJgKdWnDzphND1ePa11oQZC7u5WcpDvPLJFWcAHwuYd4A2EeKfnwR1hdpY2PdK28StuVuV2H6jk7CgxitBNu9yRHBrXWanJ7R4FtoTsXf3YJvZUoDnNyRfoy1M19x6dcppge7zUZ2G4dSNcx1cpF6zM + [1]:com.webank.weid.protocol.base.AuthenticationProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#keys-1521a0db + type: Ed25519VerificationKey2020 + controller: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + publicKeyMultibase: z5rrf3uPPK5AxXoWX7R2rpPkFHwj3ZoHnaPuHXj7CDt3cC5qRR5ihZSQGgBdTW5QZbthqndkkWXRVqHd3m5dPGJYaR8YEn7K32eL2mUMYLRxjSx7JfxAPYhB1gb6WvtnS24y6JRNahisBLXvXAcjM3PfKM32mMAipJZRXdaQr1SGUU4M9mYjDj2xNA96nz23yaZ8qpkxM9xJ7cUSR9w6Lo48 + service:(java.util.ArrayList) + [0]:com.webank.weid.protocol.base.ServiceProperty + id: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a#04b8d8ae + type: WeIdentity + serviceEndpoint: https://github.com/WeBankBlockchain/WeIdentity + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +6. registerCpt +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.console.weIdServiceConsole.registerCpt + 接口定义: ResponseData registerCpt(CptMapArgs args, Integer cptId) + 接口描述: 传入WeIdentity DID,JsonSchema(Map类型), cptId 和其对应的私钥,注册指定cptId的CPT,将cpt保存在本地文件,名字为:Cpt[cptId],返回CPT编号和版本。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - args + - CptMapArgs + - Y + - Map类型参数注册CPT + - + * - cptId + - Integer + - Y + - 指定的cptId + - + + +com.webank.weid.protocol.request.CptMapArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CptBaseInfo + - + - CPT基础数据,见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - WEID_INVALID + - 100101 + - WeIdentity DID无效 + * - WEID_PRIVATEKEY_INVALID + - 100103 + - 私钥无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥与WeIdentity DID不匹配 + * - WEID_AUTHORITY_INVALID + - 100109 + - 授权信息无效 + * - CPT_JSON_SCHEMA_INVALID + - 100301 + - schema无效 + * - CPT_EVENT_LOG_NULL + - 100304 + - 交易日志异常 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + * - CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX + - 500302 + - 为权威机构生成的cptId超过上限 + * - CPT_PUBLISHER_NOT_EXIST + - 500303 + - CPT发布者的WeIdentity DID不存在 + * - CPT_ALREADY_EXIST + - 500304 + - CPT已经存在 + * - CPT_NO_PERMISSION + - 500305 + - CPT无权限 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, "cpt template"); + cptJsonSchema.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = { "F", "M" }; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap propertitesMap4 = new HashMap(2); + propertitesMap4.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap4.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is id"); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchemaKeys.put("id", propertitesMap4); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = { "id", "name", "gender" }; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + auth.setAuthenticationMethodId(DataToolUtils.publicKeyStrFromPrivate(new BigInteger("60866441986950167911324536025850958917764441489874006048340539971987791929772")) + "#keys-0"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = weIdServiceConsole.registerCpt(cptMapArgs, 101); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 101 + cptVersion: 1 + errorCode: 0 + errorMessage: success + transactionInfo: null + + +---- + +7. queryCpt +~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.queryCpt + 接口定义:ResponseData queryCpt(Integer cptId) + 接口描述: 根据CPT编号查询CPT信息。 + +**接口入参**\ : java.lang.Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - cptId + - Integer + - Y + - cptId编号 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Cpt + - + - CPT内容,见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +com.webank.weid.protocol.base.Cpt + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptJsonSchema + - Map + - Map类型的cptJsonSchema信息 + - + * - cptBaseInfo + - CptBaseInfo + - + - CPT基础数据,见下 + * - cptMetaData + - CptMetaData + - + - CPT元数据内部类,见下 + + +com.webank.weid.protocol.base.CptBaseInfo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptId + - Integer + - cpId编号 + - + * - cptVersion + - Integer + - 版本号 + - + + +com.webank.weid.protocol.base.Cpt.MetaData + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - cptPublisher + - String + - CPT发布者的WeIdentity DID + - WeIdentity DID格式数据 + * - cptSignature + - String + - 签名数据 + - cptPublisher与cptJsonSchema拼接的签名数据 + * - updated + - long + - 更新时间 + - + * - created + - long + - 创建日期 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - TRANSACTION_TIMEOUT + - 160001 + - 超时 + * - TRANSACTION_EXECUTE_ERROR + - 160002 + - 交易错误 + * - UNKNOW_ERROR + - 160003 + - 未知异常 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - CPT_NOT_EXISTS + - 500301 + - CPT不存在 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + Integer cptId = Integer.valueOf(1017); + ResponseData response = weIdServiceConsole.queryCpt(cptId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.Cpt) + cptBaseInfo:(com.webank.weid.protocol.base.CptBaseInfo) + cptId: 1017 + cptVersion: 1 + cptJsonSchema:(java.util.HashMap) + $schema: http://json-schema.org/draft-04/schema# + type: object + properties:(java.util.LinkedHashMap) + age:(java.util.LinkedHashMap) + description: the age of certificate owner + type: number + gender:(java.util.LinkedHashMap) + description: the gender of certificate owner + enum:(java.util.ArrayList) + [0]:F + [1]:M + type: string + name:(java.util.LinkedHashMap) + description: the name of certificate owner + type: string + required:(java.util.ArrayList) + [0]:name + [1]:age + metaData:(com.webank.weid.protocol.base.Cpt$MetaData) + cptPublisher: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + cptSignature: G/YGY8Ftj9jPRdtr4ym+19M4/K6x9RbmRiV9JkryXeQGFr8eukDCBAcbinnNpF2N3Eo72bvxNqJOKx4ohWIus0Y= + created: 1560415607673 + updated: 0 + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +8. registerPolicy +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.console.weIdServiceConsole.registerPolicy + 接口定义: ResponseData registerPolicy(String policyJson, WeIdAuthentication auth) + 接口描述: 传入claimPolicy的Json序列化字符串,注册随机生成claimPolicyId的claimPolicy,将claimPolicy保存在本地文件,名字为:Policy[policyId],返回claimPolicy编号。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - policyJson + - String + - Y + - claimPolicy的Json序列化字符串 + - + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - claimPolicy的Id + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + WeIdAuthentication auth = new WeIdAuthentication(); + auth.setWeId(WeIdUtils.getWeIdFromPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772")); + auth.setAuthenticationMethodId(DataToolUtils.publicKeyStrFromPrivate(new BigInteger("60866441986950167911324536025850958917764441489874006048340539971987791929772")) + "#keys-0"); + auth.setWeIdPrivateKey(new WeIdPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772")); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + ResponseData registerResp = weIdServiceConsole.registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + + +.. code-block:: text + + 返回数据如下: + result: 101 + errorCode: 0 + errorMessage: success + transactionInfo: null + + +---- + +9. getClaimPolicy +~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.getClaimPolicy + 接口定义:ResponseData getClaimPolicy(Integer policyId) + 接口描述: 根据policyId查询ClaimPolicy信息。 + +**接口入参**\ : java.lang.Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - policyId + - Integer + - Y + - policy编号 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - ClaimPolicy + - + - ClaimPolicy内容,见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +com.webank.weid.protocol.base.ClaimPolicy + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - fieldsToBeDisclosed + - String + - policy的Json序列化字符串 + - + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + Integer policyId = Integer.valueOf(1017); + ResponseData response = weIdServiceConsole.getClaimPolicy(policyId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.ClaimPolicy) + fieldsToBeDisclosed: "{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}" + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +10. registerPresentationPolicy +~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称: com.webank.weid.service.console.weIdServiceConsole.registerPresentationPolicy + 接口定义: ResponseData registerPresentationPolicy(List claimPolicyIdList, WeIdAuthentication auth) + 接口描述: 传入一组claimPolicyId,注册随机生成presentationId的presentationPolicy,将presentationPolicy保存在本地文件,名字为:Presentation[presentationId],返回presentationPolicy编号。 + +**接口入参**\ : + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - claimPolicyIdList + - List + - Y + - 一组claimPolicyId + - + +List + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weIdAuthentication + - WeIdAuthentication + - Y + - 认证信息,包含WeIdentity DID和私钥 + - 用于WeIdentity DID的身份认证 + * - cptJsonSchema + - Map + - Y + - Map类型的JsonSchema信息 + - 基本使用见调用示例 + + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - CPT发布者的WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥值 + - 使用十进制数字表示 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Integer + - presentationPolicy的Id + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + WeIdAuthentication auth = new WeIdAuthentication(); + auth.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + auth.setAuthenticationMethodId(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey)) + "#keys-0"); + auth.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + List claimPolicyIdList = new ArrayList<>(); + ResponseData registerResp = weIdServiceConsole.registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + registerResp = weIdServiceConsole.registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + registerResp = weIdServiceConsole.registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + ClaimPolicy claimPolicyFromChain = weIdServiceConsole.getClaimPolicy(registerResp.getResult()).getResult(); + Assert.assertFalse(StringUtils.isEmpty(claimPolicyFromChain.getFieldsToBeDisclosed())); + System.out.println(claimPolicyFromChain.getFieldsToBeDisclosed()); + ResponseData presentationResp = weIdServiceConsole.registerPresentationPolicy(claimPolicyIdList, auth); + +.. code-block:: text + + 返回数据如下: + result: 101 + errorCode: 0 + errorMessage: success + transactionInfo: null + +---- + +11. getPresentationPolicy +~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.weIdServiceConsole.getPresentationPolicy + 接口定义:ResponseData getPresentationPolicy(Integer presentationPolicyId) + 接口描述: 根据presentationPolicyId查询PresentationPolicy信息。 + +**接口入参**\ : java.lang.Integer + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - presentationPolicyId + - Integer + - Y + - PresentationPolicy编号 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - 此接口返回的code + * - errorMessage + - String + - 返回结果描述 + - + * - result + - PresentationPolicyE + - + - PresentationPolicyE内容,见下 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +com.webank.weid.protocol.base.PresentationPolicyE + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - Integer + - presentationPolicy的编号 + - + * - orgId + - Integer + - 创建该presentationPolicy的组织 + - + * - policy + - Map + - 不同claimPolicyId对应的ClaimPolicy + - + * - extra + - Map + - 额外的特定信息 + - + * - policyType + - String + - 所包含的policy类型 + - 有original和ZKP类型,默认original + + +**调用示例** + +.. code-block:: java + + WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + Integer presentationPolicyId = Integer.valueOf(1017); + ResponseData response = weIdServiceConsole.getPresentationPolicy(presentationPolicyId); + + +.. code-block:: text + + 返回数据如下: + result:(com.webank.weid.protocol.base.PresentationPolicyE) + id: 62 + orgId:null + policyPublisherWeId: did:weid:0:0x82cf6d7c796126673238eae72d4d81f73596b04a + policy:(java.util.LinkedHashMap) + 81:(com.webank.weid.protocol.base.ClaimPolicy) + fieldsToBeDisclosed: {"age":0,"gender":0,"id":0,"name":0} + 65:(com.webank.weid.protocol.base.ClaimPolicy) + fieldsToBeDisclosed: {"age":0,"gender":0,"id":0,"name":0} + 10:(com.webank.weid.protocol.base.ClaimPolicy) + fieldsToBeDisclosed: {"age":0,"gender":0,"id":0,"name":0} + extra:null + policyType: original + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +CredentialServiceConsole +^^^^^^^^^^^ + +12. createCredential +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.CredentialServiceConsole.createCredential + 接口定义: ResponseData createCredential(CreateCredentialPojoArgs args) + 接口描述: 根据传入的claim对象生成Credential。 + +**接口入参**\ : + +com.webank.weid.protocol.request.CreateCredentialPojoArgs + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - cptId + - Integer + - Y + - CPT ID + - + * - issuer + - String + - Y + - WeIdentity DID + - + * - expirationDate + - Long + - Y + - 到期时间 + - + * - claim + - T + - Y + - 创建凭证需要的claim数据,参数类型为泛型,为POJO对象(不同的CPT对应不同的POJO类)。 + - 需要通过build-tool工具根据CPT ID生成对应的jar包, + * - weIdAuthentication + - WeIdAuthentication + - Y + - weId身份信息 + - + * - type + - CredentialType + - N + - 凭证类型enum,默认为Original,可选ZKP类型和Lite类型 + - + +com.webank.weid.protocol.base.WeIdAuthentication + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - weId + - String + - Y + - WeIdentity DID + - WeIdentity DID的格式传入 + * - weIdPublicKeyId + - String + - N + - 公钥Id + - + * - weIdPrivateKey + - WeIdPrivateKey + - Y + - + - 交易私钥,见下 + +com.webank.weid.protocol.base.WeIdPrivateKey + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - privateKey + - String + - Y + - 私钥 + - 使用十进制数字表示 + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - context + - String + - + - + * - type + - List + - + - + * - id + - String + - 证书ID + - + * - cptId + - Integer + - cptId + - + * - issuer + - String + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - 创建日期 + - + * - expirationDate + - Long + - 到期日期 + - + * - claim + - Map + - Claim数据 + - + * - proof + - Map + - 签名数据结构体 + - + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - WEID_PRIVATEKEY_DOES_NOT_MATCH + - 100106 + - 私钥和weid不匹配 + * - CREDENTIAL_ERROR + - 100400 + - credential处理未知异常 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期无效 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim非法 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + +**调用示例** + +.. code-block:: java + + CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setAuthenticationMethodId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialServiceConsole.createCredential(createCredentialPojoArgs); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: 04a3e89d-825a-49fe-b8f5-8ccb9f487a52 + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560420878712 + expirationDate: 1560470944120 + claim:(java.util.HashMap) + gender: F + name: zhangsan + age: 22 + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + gender: ibu7f + name: el1w8 + age: ajqkr + created: 1560420878712 + type: Secp256k1 + signatureValue: G7UPiw08P5E9dEcSJEo9zpKu/nsUrpn00xDE+mwDXn9gJEohIlRUX5XTGQB4G1w3yThp6R/2RqjUYkuQTaUXbIU= + type:(java.util.ArrayList) + [0]:VerifiableCredential + errorCode: 0 + errorMessage: success + transactionInfo:null + + +---- + +13. createSelectiveCredential +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.CredentialServiceConsole.createSelectiveCredential + 接口定义: ResponseData createSelectiveCredential(CredentialPojo credentialPojo, ClaimPolicy claimPolicy) + 接口描述: 通过原始凭证和披露策略,创建基于hash连接选择性披露的Credential。 + +.. note:; + + ClaimPolicy内部对选择性披露的策略定义在fieldsToBeDisclosed。它是一个Json字符串,和Claim中定义的Key完全对应,Value为1则为披露(在生成的凭证中显示为原文),Value为0则为不披露(显示为加盐的hash值)。如您的Claim包括name、gender、age三项,想披露name和age,不披露gender,则对应的ClaimPolicy为"{\"name\":1,\"gender\":0,\"age\":1}" + +.. note:: + + 注意:对于已经创建好的选择性披露凭证,不允许再次进行选择性披露。 + +**接口入参**\ : + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +com.webank.weid.protocol.base.ClaimPolicy + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - fieldsToBeDisclosed + - String + - Y + - 披露配置 + - 根据claim匹配的结构,为一个Json字符串,和Claim字段格式匹配。详见调用示例 + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - CredentialPojo + - 凭证对象 + - 业务数据 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ERROR + - 100400 + - Credential标准错误 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_CLAIM_POLICY_NOT_EXIST + - 100420 + - 披露策略为null + * - CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL + - 100423 + - policy披露信息非法 + * - CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM + - 100427 + - 披露策略与Claim不匹配 + * - CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL + - 100428 + - 披露数据格式错误 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数非法 + * - CREDENTIAL_NOT_SUPPORT_SELECTIVE_DISCLOSURE + - 100440 + - lite credential不支持选择性披露 + + +**调用示例** + +.. code-block:: java + + CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs + .setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs + .setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey( + "60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + weIdAuthentication.setAuthenticationMethodId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = + credentialServiceConsole.createCredential(createCredentialPojoArgs); + + // 选择性披露 + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1}"); + ResponseData selectiveResponse = + credentialServiceConsole.createSelectiveCredential(response.getResult(), claimPolicy); + + +.. code-block:: text + + 返回结果如: + result:(com.webank.weid.protocol.base.CredentialPojo) + context: https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1 + id: c4f8ca00-7c1b-4ba0-993f-008106075d9c + cptId: 1017 + issuer: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7 + issuanceDate: 1560420975268 + expirationDate: 1560471040676 + claim:(java.util.HashMap) + gender: 0x0756ccf78a0ebd5bd186b054376f1e9d86139bf04f660e9171a74673e5a21c75 + name: zhangsan + age: 22 + proof:(java.util.HashMap) + creator: did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0 + salt:(java.util.HashMap) + gender: 0 + name: rr3g0 + age: 9ysgr + created: 1560420975268 + type: Secp256k1 + signatureValue: GxVcZJFEnC7w+ZKOZAjmKy5JfFxoEFqffmCMvbUnVYmzEVKIUtDCiDmokZ2X3jIV/uFvUHQ4DWXksrD6Opr1vLo= + type:(java.util.ArrayList) + [0]:VerifiableCredential + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +14. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.CredentialServiceConsole.verify + 接口定义: ResponseData verify(String issuerPublicKey, CredentialPojo credential) + 接口描述: 使用提供的签发者公钥验证Credential,前提是该Credential对应的CPT文件保存在本地,如果没有请先使用registerCpt将CPT保存至本地文件 + +**接口入参**\ : + +String + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - issuerPublicKey + - String + - Y + - 公钥 + - + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - 获取weIdDocument异常 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_PUBLIC_KEY_NOT_EXISTS + - 100421 + - 公钥不存在 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setAuthenticationMethodId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialServiceConsole.createCredential(createCredentialPojoArgs); + + String issuerPublicKey = "9202079291855274840499629257327649367489192973501473466426182121217769706994308329953406897395674428921435762028726727399019951049448689033610431403383875"; + ResponseData responseVerify = credentialServiceConsole.verify(issuerPublicKey, response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +15. verify +~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.console.CredentialServiceConsole.verify + 接口定义: ResponseData verify(WeIdDocument weIdDocument, CredentialPojo credential) + 接口描述: 使用提供的签发者的WeIdDocument来验证Credential,前提是该Credential对应的CPT文件保存在本地,如果没有请先使用registerCpt将CPT保存至本地文件。 + +**接口入参**\ : + +com.webank.weid.protocol.base.WeIdDocument + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - WeIdentity DID + - + * - authentication + - List\ :raw-html-m2r:`` + - + - 认证方集合,见下 + * - service + - List\ :raw-html-m2r:`` + - + - 服务端点集合,见下 + + +com.webank.weid.protocol.base.AuthenticationProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - verification method id + * - type + - String + - 类型 + - 默认为:Ed25519VerificationKey2020 + * - controller + - String + - 方法拥有人 + - verification method controller + * - publicKeyMultibase + - String + - 验证公钥 + - 使用base58编码的公钥 + + +com.webank.weid.protocol.base.ServiceProperty + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - id + - String + - 方法编号 + - + * - type + - String + - 类型 + - + * - serviceEndpoint + - String + - 联系/服务方式 + - 邮箱、github个人主页等 + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - Boolean + - 验证结果 + - 业务数据 + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_ISSUER_MISMATCH + - 100403 + - issuerWeId跟Credential中的issuer不匹配 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名验证不通过 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_CLAIM_DATA_ILLEGAL + - 100411 + - Claim数据无效 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_TYPE_IS_NULL + - 100414 + - type为空 + * - CREDENTIAL_CPT_NOT_EXISTS + - 100416 + - cpt不存在 + * - CREDENTIAL_WEID_DOCUMENT_ILLEGAL + - 100417 + - 获取weIdDocument异常 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_EXCEPTION_VERIFYSIGNATURE + - 100419 + - 签名验证异常 + * - CREDENTIAL_PUBLIC_KEY_NOT_EXISTS + - 100421 + - 公钥不存在 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - CREDENTIAL_SALT_ILLEGAL + - 100430 + - 盐值非法 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setAuthenticationMethodId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialServiceConsole.createCredential(createCredentialPojoArgs); + + WeIdDocument weIdDocument = weIdServiceConsole.createWeIdDocument("9202079291855274840499629257327649367489192973501473466426182121217769706994308329953406897395674428921435762028726727399019951049448689033610431403383875").getResult(); + ResponseData responseVerify = credentialServiceConsole.verify(weIdDocument, response.getResult()); + + +.. code-block:: text + + 返回结果如: + result: true + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +16. getCredentialPojoHash +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**基本信息** + +.. code-block:: text + + 接口名称:com.webank.weid.service.rpc.CredentialPojoService.getCredentialPojoHash + 接口定义:ResponseData getCredentialHash(CredentialPojo args) + 接口描述: 传入CredentialPojo信息生成CredentialPojo整体的Hash值,一般在生成Evidence时调用。 + +**接口入参**\ : com.webank.weid.protocol.base.CredentialPojo + + +com.webank.weid.protocol.base.CredentialPojo + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 非空 + - 说明 + - 备注 + * - context + - String + - Y + - + - + * - type + - List + - Y + - + - + * - id + - String + - Y + - 证书ID + - + * - cptId + - Integer + - Y + - cptId + - + * - issuer + - String + - Y + - issuer 的 WeIdentity DID + - + * - issuanceDate + - Long + - Y + - 创建日期 + - + * - expirationDate + - Long + - Y + - 到期日期 + - + * - claim + - Map + - Y + - Claim数据 + - + * - proof + - Map + - Y + - 签名数据结构体 + - + +**接口返回**\ : com.webank.weid.protocol.response.ResponseData\; + +.. list-table:: + :header-rows: 1 + + * - 名称 + - 类型 + - 说明 + - 备注 + * - errorCode + - Integer + - 返回结果码 + - + * - errorMessage + - String + - 返回结果描述 + - + * - result + - String + - 返回结果值 + - + * - transactionInfo + - TransactionInfo + - null + - 纯功能接口没有交易信息 + +**此方法返回code** + +.. list-table:: + :header-rows: 1 + + * - enum + - code + - desc + * - SUCCESS + - 0 + - 成功 + * - CPT_ID_ILLEGAL + - 100303 + - cptId无效 + * - CREDENTIAL_EXPIRED + - 100402 + - 过期 + * - CREDENTIAL_SIGNATURE_BROKEN + - 100405 + - 签名破坏 + * - CREDENTIAL_CREATE_DATE_ILLEGAL + - 100408 + - 创建日期格式非法 + * - CREDENTIAL_EXPIRE_DATE_ILLEGAL + - 100409 + - 到期日期格式非法 + * - CREDENTIAL_CLAIM_NOT_EXISTS + - 100410 + - Claim数据不能为空 + * - CREDENTIAL_ID_NOT_EXISTS + - 100412 + - ID为空 + * - CREDENTIAL_CONTEXT_NOT_EXISTS + - 100413 + - context为空 + * - CREDENTIAL_ISSUER_INVALID + - 100418 + - WeIdentity DID无效 + * - CREDENTIAL_SIGNATURE_TYPE_ILLEGAL + - 100429 + - 验证签名类型异常 + * - ILLEGAL_INPUT + - 160004 + - 参数为空 + + +**调用示例** + +.. code-block:: java + + + CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + CreateCredentialPojoArgs> createCredentialPojoArgs = new CreateCredentialPojoArgs>(); + createCredentialPojoArgs.setCptId(1017); + createCredentialPojoArgs.setIssuer("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 100); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7"); + + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("60866441986950167911324536025850958917764441489874006048340539971987791929772"); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + weIdAuthentication.setAuthenticationMethodId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b65600e7#key0"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + Map claim = new HashMap(); + claim.put("name", "zhangsan"); + claim.put("gender", "F"); + claim.put("age", 22); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = credentialServiceConsole.createCredential(createCredentialPojoArgs); + + ResponseData resp = credentialServiceConsole.getCredentialPojoHash(response.getResult()); + +.. code-block:: text + + 返回结果如: + result: 0x06173e4b714d57565ae5ddf23c4e84cb0a9824cb72eab476303d2dd1cc0a4728 + errorCode: 0 + errorMessage: success + transactionInfo:null + +---- + +异常场景对接口的影响 +--------------------- + +- mysql或redis连接异常受影响接口:Persistence相关和serialize密文。 + +- 节点连接异常受影响接口:createWeId,createEvidence,registerAuthorityIssuer,RegisterIssuerType,RegisterCpt,VerifyCredentialWithSpecifiedPubKey,GetWeIdDocument,verifyLiteCredential。 + +- 节点连接正常,但不满足3f+1受影响接口:createWeId,createEvidence,registerAuthorityIssuer,RegisterIssuerType,RegisterCpt。 + diff --git a/docs/zh_CN/index.rst b/docs/zh_CN/index.rst new file mode 100644 index 00000000..cc9b9299 --- /dev/null +++ b/docs/zh_CN/index.rst @@ -0,0 +1,11 @@ +.. role:: raw-html-m2r(raw) + :format: html + +.. include:: docs/README.rst + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + docs/weidentity-java-sdk-doc.rst + 返回首页 \ No newline at end of file diff --git a/docs/zh_CN/make.bat b/docs/zh_CN/make.bat new file mode 100644 index 00000000..7893348a --- /dev/null +++ b/docs/zh_CN/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/gradle.properties b/gradle.properties index babb0560..5b4ca14d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,8 @@ -org.gradle.jvmargs='-Dfile.encoding=UTF-8' \ No newline at end of file +org.gradle.jvmargs='-Dfile.encoding=UTF-8' +jdkTlsNamedGroups=secp256r1,secp256k1 +repoType=zn +signing.keyId= +signing.password= +signing.secretKeyRingFile= +sonatypeUsername= +sonatypePassword= \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..5c2d1cf0 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..bb8b2fc2 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..83f2acfd --- /dev/null +++ b/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/hash b/hash new file mode 100644 index 00000000..2f44862c --- /dev/null +++ b/hash @@ -0,0 +1 @@ +0x048edac4057beac4f70a7c11fddf2218125336a04b70a52ca771aa98ba648a3d \ No newline at end of file diff --git a/lib/WeDPR-Java-SDK.jar b/lib/WeDPR-Java-SDK.jar new file mode 100644 index 00000000..3d3ee6bb Binary files /dev/null and b/lib/WeDPR-Java-SDK.jar differ diff --git a/lib/WeDPR-ecies.jar b/lib/WeDPR-ecies.jar new file mode 100644 index 00000000..9176e599 Binary files /dev/null and b/lib/WeDPR-ecies.jar differ diff --git a/lib/web3sdk.jar b/lib/web3sdk.jar deleted file mode 100644 index 4aa73348..00000000 Binary files a/lib/web3sdk.jar and /dev/null differ diff --git a/private_key b/private_key new file mode 100644 index 00000000..3bceba5a --- /dev/null +++ b/private_key @@ -0,0 +1 @@ +49191370627614877492996337821917274297863513005433547861103892894089436256261 \ No newline at end of file diff --git a/public_key b/public_key new file mode 100644 index 00000000..098cedf9 --- /dev/null +++ b/public_key @@ -0,0 +1 @@ +13079093397463814932731720163442777403208788175453836227824139092404945067394266611910031425181012754616377192193136435818972874637291518463471522281921222 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..82bb3e4f --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +// Preserve the original java sdk name +rootProject.name = "weid-java-sdk" \ No newline at end of file diff --git a/src/demo/com/webank/weid/demo/DemoBase.java b/src/demo/com/webank/weid/demo/DemoBase.java deleted file mode 100644 index c1595921..00000000 --- a/src/demo/com/webank/weid/demo/DemoBase.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify it under the terms of - * the GNU Lesser General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.demo; - -import java.math.BigInteger; -import org.bcos.contract.tools.ToolConf; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * Base class for demo. - * - * @author v_wbgyang - */ -public abstract class DemoBase { - - public static String privKey; - protected static ApplicationContext context; - - static { - context = new ClassPathXmlApplicationContext(new String[] { - "classpath:SpringApplicationContext-test.xml", - "classpath:applicationContext.xml"}); - - ToolConf toolConf = context.getBean(ToolConf.class); - privKey = new BigInteger(toolConf.getPrivKey(), 16).toString(); - } -} diff --git a/src/demo/com/webank/weid/demo/DemoService.java b/src/demo/com/webank/weid/demo/DemoService.java deleted file mode 100644 index 65c7bb74..00000000 --- a/src/demo/com/webank/weid/demo/DemoService.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.demo; - -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.protocol.base.AuthorityIssuer; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.AuthorityIssuerService; -import com.webank.weid.rpc.CptService; -import com.webank.weid.rpc.CredentialService; -import com.webank.weid.rpc.WeIdService; -import java.util.Date; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class DemoService { - - @Autowired - private AuthorityIssuerService authorityIssuerService; - - @Autowired - private CptService cptService; - - @Autowired - private CredentialService credentialService; - - @Autowired - private WeIdService weIdService; - - /** - * create WeIdentity DID. - */ - public CreateWeIdDataResult createWeId() throws RuntimeException { - - // create WeIdentity DID,publicKey,privateKey - ResponseData responseCreate = weIdService.createWeId(); - // check result is success - if (responseCreate.getErrorCode() != ErrorCode.SUCCESS.getCode()) { - throw new RuntimeException(responseCreate.getErrorMessage()); - } - return responseCreate.getResult(); - } - - /** - * setPublicKey. - */ - public void setPublicKey(CreateWeIdDataResult createResult, String keyType) - throws RuntimeException { - - // setPublicKey for this WeId - SetPublicKeyArgs setPublicKeyArgs = new SetPublicKeyArgs(); - setPublicKeyArgs.setWeId(createResult.getWeId()); - setPublicKeyArgs.setPublicKey(createResult.getUserWeIdPublicKey().getPublicKey()); - setPublicKeyArgs.setType(keyType); - setPublicKeyArgs.setUserWeIdPrivateKey(createResult.getUserWeIdPrivateKey()); - ResponseData responseSetPub = weIdService.setPublicKey(setPublicKeyArgs); - // check is success - if (responseSetPub.getErrorCode() != ErrorCode.SUCCESS.getCode() - || !responseSetPub.getResult()) { - throw new RuntimeException(responseSetPub.getErrorMessage()); - } - } - - /** - * setService. - */ - public void setService( - CreateWeIdDataResult createResult, - String serviceType, - String serviceEnpoint) - throws RuntimeException { - - // setService for this WeIdentity DID - SetServiceArgs setServiceArgs = new SetServiceArgs(); - setServiceArgs.setWeId(createResult.getWeId()); - setServiceArgs.setType(serviceType); - setServiceArgs.setServiceEndpoint(serviceEnpoint); - setServiceArgs.setUserWeIdPrivateKey(createResult.getUserWeIdPrivateKey()); - ResponseData responseSetSer = weIdService.setService(setServiceArgs); - // check is success - if (responseSetSer.getErrorCode() != ErrorCode.SUCCESS.getCode() - || !responseSetSer.getResult()) { - throw new RuntimeException(responseSetSer.getErrorMessage()); - } - } - - /** - * setAuthenticate. - */ - public void setAuthenticate(CreateWeIdDataResult createResult, String authType) - throws RuntimeException { - - // setAuthenticate for this WeIdentity DID - SetAuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); - setAuthenticationArgs.setWeId(createResult.getWeId()); - setAuthenticationArgs.setType(authType); - setAuthenticationArgs.setPublicKey(createResult.getUserWeIdPublicKey().getPublicKey()); - setAuthenticationArgs.setUserWeIdPrivateKey(createResult.getUserWeIdPrivateKey()); - ResponseData responseSetAuth = - weIdService.setAuthentication(setAuthenticationArgs); - // check is success - if (responseSetAuth.getErrorCode() != ErrorCode.SUCCESS.getCode() - || !responseSetAuth.getResult()) { - throw new RuntimeException(responseSetAuth.getErrorMessage()); - } - } - - /** - * getWeIdDom. - */ - public WeIdDocument getWeIdDom(String weId) throws RuntimeException { - - // get weIdDom - ResponseData responseResult = weIdService.getWeIdDocument(weId); - // check result - if (responseResult.getErrorCode() != ErrorCode.SUCCESS.getCode() - || responseResult.getResult() == null) { - throw new RuntimeException(responseResult.getErrorMessage()); - } - return responseResult.getResult(); - } - - /** - * regist cpt. - */ - public CptBaseInfo registCpt(CreateWeIdDataResult weIdResult, String cptJsonSchema) - throws RuntimeException { - - RegisterCptArgs registerCptArgs = new RegisterCptArgs(); - WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); - weIdPrivateKey.setPrivateKey(weIdResult.getUserWeIdPrivateKey().getPrivateKey()); - registerCptArgs.setCptPublisher(weIdResult.getWeId()); - registerCptArgs.setCptPublisherPrivateKey(weIdPrivateKey); - registerCptArgs.setCptJsonSchema(cptJsonSchema); - ResponseData response = cptService.registerCpt(registerCptArgs); - // check result - if (response.getErrorCode() != ErrorCode.SUCCESS.getCode() - || response.getResult() == null) { - throw new RuntimeException(response.getErrorMessage()); - } - return response.getResult(); - } - - /** - * regist authority issuer. - */ - public void registerAuthorityIssuer( - CreateWeIdDataResult weIdResult, - String name, - String accValue) - throws RuntimeException { - - AuthorityIssuer authorityIssuerResult = new AuthorityIssuer(); - authorityIssuerResult.setWeId(weIdResult.getWeId()); - authorityIssuerResult.setName(name); - authorityIssuerResult.setCreated(new Date().getTime()); - authorityIssuerResult.setAccValue(accValue); - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); - registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuerResult); - registerAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(DemoBase.privKey); - - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - BeanUtil.print(response); - - // check is success - if (response.getErrorCode() != ErrorCode.SUCCESS.getCode() || !response.getResult()) { - throw new RuntimeException(response.getErrorMessage()); - } - } - - /** - * create Credential. - */ - public Credential createCredential( - CreateWeIdDataResult weIdResult, - Integer cptId, - String claim, - long expirationDate) - throws Exception { - - CreateCredentialArgs args = new CreateCredentialArgs(); - args.setClaim(claim); - args.setCptId(cptId); - args.setExpirationDate(expirationDate); - args.setIssuer(weIdResult.getWeId()); - WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); - weIdPrivateKey.setPrivateKey(weIdResult.getUserWeIdPrivateKey().getPrivateKey()); - args.setWeIdPrivateKey(weIdPrivateKey); - ResponseData response = credentialService.createCredential(args); - // check result - if (response.getErrorCode() != ErrorCode.SUCCESS.getCode() - || response.getResult() == null) { - throw new RuntimeException(response.getErrorMessage()); - } - return response.getResult(); - } - - /** - * verifyCredential. - */ - public boolean verifyCredential(Credential credential) throws RuntimeException { - ResponseData response = credentialService.verifyCredential(credential); - // check is success - if (response.getErrorCode() != ErrorCode.SUCCESS.getCode()) { - throw new RuntimeException(response.getErrorMessage()); - } - return response.getResult(); - } -} diff --git a/src/demo/com/webank/weid/demo/DemoTest.java b/src/demo/com/webank/weid/demo/DemoTest.java deleted file mode 100644 index 01864f40..00000000 --- a/src/demo/com/webank/weid/demo/DemoTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.demo; - -import com.webank.weid.common.BeanUtil; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.util.DateUtils; -import org.springframework.stereotype.Component; - -/** - * WeIdentity DID demo. - * - * @author v_wbgyang - */ -@Component -public class DemoTest extends DemoBase { - - /** jsonSchema. */ - private static String schema = - "{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"/etc/fstab\",\"description\":\"JSON representation of /etc/fstab\",\"type\":\"object\",\"properties\":{\"swap\":{\"$ref\":\"#/definitions/mntent\"}},\"patternProperties\":{\"^/([^/]+(/[^/]+)*)?$\":{\"$ref\":\"#/definitions/mntent\"}},\"required\":[\"/\",\"swap\"],\"additionalProperties\":false,\"definitions\":{\"mntent\":{\"title\":\"mntent\",\"description\":\"An fstab entry\",\"type\":\"object\",\"properties\":{\"device\":{\"type\":\"string\"},\"fstype\":{\"type\":\"string\"},\"options\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"string\"}},\"dump\":{\"type\":\"integer\",\"minimum\":0},\"fsck\":{\"type\":\"integer\",\"minimum\":0}},\"required\":[\"device\",\"fstype\"],\"additionalItems\":false}}}"; - - /** claim. */ - private static String schemaData = - "{\"/\":{\"device\":\"/dev/sda2\",\"fstype\":\"btrfs\",\"options\":[\"ssd\"]},\"swap\":{\"device\":\"/dev/sda2\",\"fstype\":\"swap\"},\"/tmp\":{\"device\":\"tmpfs\",\"fstype\":\"tmpfs\",\"options\":[\"size=64M\"]},\"/var/lib/mysql\":{\"device\":\"/dev/data/mysql\",\"fstype\":\"btrfs\"}}"; - - /** - * main of demo. - */ - public static void main(String[] args) throws Exception { - - // get service instance - DemoService demo = context.getBean(DemoService.class); - - // create weId - CreateWeIdDataResult createWeId = demo.createWeId(); - BeanUtil.print(createWeId); - - // set WeIdentity DID - demo.setPublicKey(createWeId, "secp256k1"); - demo.setService(createWeId, - "drivingCardService", - "https://weidentity.webank.com/endpoint/8377464"); - demo.setAuthenticate(createWeId, "RsaSignatureAuthentication2018"); - - // get WeId Dom - WeIdDocument weIdDom = demo.getWeIdDom(createWeId.getWeId()); - System.out.println("----------------------"); - BeanUtil.print(weIdDom); - - // regist authority issuer - demo.registerAuthorityIssuer(createWeId, "webank", "0"); - - // registCpt - CptBaseInfo cptResult = demo.registCpt(createWeId, schema); - System.out.println("----------------------"); - BeanUtil.print(cptResult); - - // create Credential - Credential credential = demo.createCredential(createWeId, - cptResult.getCptId(), - schemaData, - DateUtils.convertStringToDate("2019-10-11T18:09:42Z").getTime()); - System.out.println("----------------------"); - BeanUtil.print(credential); - - boolean result = demo.verifyCredential(credential); - if (result) { - System.out.println("verify success"); - } else { - System.out.println("verify fail"); - } - } -} diff --git a/src/demo/com/webank/weid/demo/DemoTest1.java b/src/demo/com/webank/weid/demo/DemoTest1.java deleted file mode 100644 index 7bfd8623..00000000 --- a/src/demo/com/webank/weid/demo/DemoTest1.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify it under the terms of - * the GNU Lesser General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.demo; - -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.protocol.base.AuthorityIssuer; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.AuthorityIssuerService; -import com.webank.weid.rpc.CptService; -import com.webank.weid.rpc.CredentialService; -import com.webank.weid.rpc.WeIdService; -import java.math.BigInteger; -import org.bcos.contract.tools.ToolConf; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - *

- * This demo is designed to guide users to use SDK. - * - * The streamlining process is as follows: - * - * 1. Create the only full network identity and set up your public key and authenticator. If you do - * not have your own public and private keys, we provide you with a method that will automatically - * create public and private key pairs for you. Please keep your private key and identity - * information, because you need to use your private key account to verify your identity in - * subsequent operations. - * - * 2. If you want to become an authority, you can call the corresponding method to register the - * authority, but this step is not necessary. - * - * 3. You need to register an authentication template (CPT). We will return a template number. - * Please keep your template number. You need to use the template number to create credentials. - * - * 4.This step will create your credentials, using the ID, private key, CPT number and JSON string - * data corresponding to the CPT template you generated earlier. We will return you a credential - * object. You can serialize and save your credential information by yourself, such as using JSON to - * serialize and save it. - * - * 5.Any person or institution with weId status can use your credentials to verify the validity of - * your information. - *

- * - * @author v_wbgyang - * - */ -public class DemoTest1 { - - /** jsonSchema. */ - private static String schema = - "{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"/etc/fstab\",\"description\":\"JSON representation of /etc/fstab\",\"type\":\"object\",\"properties\":{\"swap\":{\"$ref\":\"#/definitions/mntent\"}},\"patternProperties\":{\"^/([^/]+(/[^/]+)*)?$\":{\"$ref\":\"#/definitions/mntent\"}},\"required\":[\"/\",\"swap\"],\"additionalProperties\":false,\"definitions\":{\"mntent\":{\"title\":\"mntent\",\"description\":\"An fstab entry\",\"type\":\"object\",\"properties\":{\"device\":{\"type\":\"string\"},\"fstype\":{\"type\":\"string\"},\"options\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"string\"}},\"dump\":{\"type\":\"integer\",\"minimum\":0},\"fsck\":{\"type\":\"integer\",\"minimum\":0}},\"required\":[\"device\",\"fstype\"],\"additionalItems\":false}}}"; - - /** claim. */ - private static String schemaData = - "{\"/\":{\"device\":\"/dev/sda2\",\"fstype\":\"btrfs\",\"options\":[\"ssd\"]},\"swap\":{\"device\":\"/dev/sda2\",\"fstype\":\"swap\"},\"/tmp\":{\"device\":\"tmpfs\",\"fstype\":\"tmpfs\",\"options\":[\"size=64M\"]},\"/var/lib/mysql\":{\"device\":\"/dev/data/mysql\",\"fstype\":\"btrfs\"}}"; - - /** - * main for DemoTest1. - * - */ - public static void main(String[] args) throws Exception { - - /* - * Because weidentity-java-sdk is implemented based on spring framework, it is necessary to - * use spring container to manage core objects. - * - * 1. The purpose of loading SpringApplicationContext-test.xml is to let spring containers - * manage core objects. In their own spring project, annotation-driven scanning of - * com.webank.weid package is required. - * - * 2. The purpose of loading applicationContext. XML is to obtain the contract deployment - * private key. If you need to register an authority, you need to use the private key. - * Otherwise, you do not have the right to register as an authority. - * - */ - System.out.println("init context..."); - ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { - "classpath:SpringApplicationContext-test.xml", "classpath:applicationContext.xml"}); - - // The purpose of this step is to get relevant service objects from the spring container. - WeIdService weIdService = context.getBean(WeIdService.class); - AuthorityIssuerService authorityIssuerService = - context.getBean(AuthorityIssuerService.class); - CptService cptService = context.getBean(CptService.class); - CredentialService credentialService = context.getBean(CredentialService.class); - ToolConf toolConf = context.getBean(ToolConf.class); - String sdkPrivKey = new BigInteger(toolConf.getPrivKey(), 16).toString(); - - // Step one: create weId and set the public key and authenticator status. - System.out.println("begin create weId..."); - - // 1. Create weId on the chain - ResponseData createWeIdResult = weIdService.createWeId(); - if (createWeIdResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || createWeIdResult.getResult() == null) { - throw new Exception(createWeIdResult.getErrorMessage()); - } - - String weId = createWeIdResult.getResult().getWeId(); - String privateKey = createWeIdResult.getResult().getUserWeIdPrivateKey().getPrivateKey(); - String publicKey = createWeIdResult.getResult().getUserWeIdPublicKey().getPublicKey(); - System.out.println("----------createWeIdResult--------------"); - System.out.println("weId:" + weId); - System.out.println("privateKey:" + privateKey); - System.out.println("publicKey:" + publicKey); - System.out.println("------------------------"); - - // 2. Set the public key on the chain - System.out.println("begin set publicKey..."); - SetPublicKeyArgs setPublicKeyArgs = new SetPublicKeyArgs(); - setPublicKeyArgs.setWeId(weId); - setPublicKeyArgs.setPublicKey(publicKey); - - setPublicKeyArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setPublicKeyArgs.getUserWeIdPrivateKey().setPrivateKey(privateKey); - - ResponseData setPubResult = weIdService.setPublicKey(setPublicKeyArgs); - if (setPubResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || !setPubResult.getResult()) { - throw new Exception(setPubResult.getErrorMessage()); - } - - // 3. Set the Authenticator on chain. - System.out.println("begin set authentication..."); - SetAuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); - setAuthenticationArgs.setWeId(weId); - setAuthenticationArgs.setPublicKey(publicKey); - setAuthenticationArgs.setType("RsaSignatureAuthentication2018"); - - setAuthenticationArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setAuthenticationArgs.getUserWeIdPrivateKey().setPrivateKey(privateKey); - - ResponseData setAuthResult = weIdService.setAuthentication(setAuthenticationArgs); - if (setAuthResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || !setAuthResult.getResult()) { - throw new Exception(setAuthResult.getErrorMessage()); - } - - // The second step: register as an authority, this step is not necessary. - System.out.println("begin regist authority issuer..."); - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); - registerAuthorityIssuerArgs.setAuthorityIssuer(new AuthorityIssuer()); - registerAuthorityIssuerArgs.getAuthorityIssuer().setWeId(weId); - registerAuthorityIssuerArgs.getAuthorityIssuer().setName("webank"); - registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue("0"); - - registerAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(sdkPrivKey); - - ResponseData registAuthResult = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - if (registAuthResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || !registAuthResult.getResult()) { - throw new Exception(registAuthResult.getErrorMessage()); - } - - // The third step: register CPT template - System.out.println("begin regist cpt..."); - RegisterCptArgs registerCptArgs = new RegisterCptArgs(); - registerCptArgs.setCptJsonSchema(schema); // Set up a template - registerCptArgs.setCptPublisher(weId); // Set template publisher - - registerCptArgs.setCptPublisherPrivateKey(new WeIdPrivateKey()); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey(privateKey); - - ResponseData cptBaseResult = cptService.registerCpt(registerCptArgs); - if (cptBaseResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || cptBaseResult.getResult() == null) { - throw new Exception(cptBaseResult.getErrorMessage()); - } - - // The fourth step: create credential information. - System.out.println("begin create credential..."); - CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); - createCredentialArgs.setClaim(schemaData); // Set data required for template - createCredentialArgs.setCptId(cptBaseResult.getResult().getCptId()); // Set cptId - createCredentialArgs.setIssuer(weId); // Set Creator of voucher - createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 1000000);// Set - // expiration - // date - - createCredentialArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(privateKey); - - ResponseData credentialResult = - credentialService.createCredential(createCredentialArgs); - if (credentialResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode() - || credentialResult.getResult() == null) { - throw new Exception(credentialResult.getErrorMessage()); - } - Credential credential = credentialResult.getResult(); - - // The fifth step: verify the voucher. - System.out.println("begin verify credential..."); - ResponseData verifyResult = credentialService.verifyCredential(credential); - if (verifyResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { - throw new Exception(verifyResult.getErrorMessage()); - } - - if (verifyResult.getResult()) { - System.out.println("credential verify success"); - } else { - System.out.println("credential verify fail"); - } - } -} diff --git a/src/main/java/com/webank/weid/app/AppCommand.java b/src/main/java/com/webank/weid/app/AppCommand.java new file mode 100644 index 00000000..b367096d --- /dev/null +++ b/src/main/java/com/webank/weid/app/AppCommand.java @@ -0,0 +1,136 @@ + + +package com.webank.weid.app; + +import com.webank.weid.constant.ErrorCode; +import com.webank.weid.exception.InitWeb3jException; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.rpc.WeIdService; +import com.webank.weid.service.impl.WeIdServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.PrintStream; + +/** + * commands for testing. + * + * @author tonychen 2019年6月11日 + */ +public class AppCommand { + + private static final Logger logger = LoggerFactory.getLogger(AppCommand.class); + + /** + * commands. + * + * @param args input + */ + public static void main(String[] args) { + + Integer result = 0; + try { + if (args.length < 2) { + System.err.println("Parameter illegal, please check your input."); + System.exit(1); + } + String command = args[0]; + if (!StringUtils.equals(command, "--checkhealth") + && !StringUtils.equals(command, "--checkweid") + && !StringUtils.equals(command, "--checkversion")) { + logger.error("[AppCommand] input command :{} is illegal.", command); + System.err.println("Parameter illegal, please check your input command."); + System.exit(1); + } + + switch (command) { + /*case "--checkhealth": + result = checkAmopHealth(args[1]); + break;*/ + case "--checkweid": + result = checkWeid(args[1]); + break; + case "--checkversion": + result = checkVersion(); + break; + default: + logger.error("[AppCommand]: the command -> {} is not supported .", command); + } + } catch (Exception e) { + logger.error("[AppCommand] execute command with exception.", e); + System.exit(1); + } + System.exit(result); + } + + private static int checkVersion() { + try { + System.setOut(new PrintStream("./sdk.out")); + String version = com.webank.weid.blockchain.util.DataToolUtils.getVersion(); + System.err.println("block chain nodes connected successfully. "); + System.err.println("the FISCO-BCOS version is: " + version); + int blockNumer = com.webank.weid.blockchain.util.DataToolUtils.getBlockNumber(); + System.err.println("the current blockNumer is: " + blockNumer); + } catch (InitWeb3jException e) { + System.err.println("ERROR: initWeb3j error:" + e.getMessage()); + logger.error("[checkVersion] checkVersion with exception.", e); + } catch (Exception e) { + System.err.println("ERROR: unknow error:" + e.getMessage()); + logger.error("[checkVersion] checkVersion with exception.", e); + } + return 0; + } + + /** + * check if the weid exists on blockchain. + * + * @param weid the weid to check + * @return ErrorCode + */ + private static Integer checkWeid(String weid) { + + WeIdService weidService = new WeIdServiceImpl(); + ResponseData resp = weidService.isWeIdExist(weid); + + if (resp.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) { + logger.info("[checkWeid] weid --> {} exists on blockchain.", weid); + System.out.println("[checkWeid] weid --> " + weid + "exists on blockchain."); + } else { + logger.error("[checkWeid] weid --> {} does not exist on blockchain. response is {}", + weid, + resp); + System.out.println("[checkWeid] weid --> " + weid + " does not exist on blockchain."); + } + return resp.getErrorCode(); + } + + /** + * check if the amop is health. + * + * @param toOrgId the orgid to test amop connection + * @return ErrorCode + */ + /*private static Integer checkAmopHealth(String toOrgId) { + + AmopServiceImpl amopService = new AmopServiceImpl(); + CheckAmopMsgHealthArgs checkAmopMsgHealthArgs = new CheckAmopMsgHealthArgs(); + checkAmopMsgHealthArgs.setMessage("hello"); + + ResponseData resp = amopService + .checkDirectRouteMsgHealth(toOrgId, checkAmopMsgHealthArgs); + + if (resp.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) { + logger.info("[checkAmopHealth] toOrgId --> {} check success.", toOrgId); + System.out.println( + "[checkAmopHealth] send amop message to OrgId -->" + toOrgId + " with success."); + } else { + logger.error("[checkAmopHealth] toOrgId --> {} check failed, response is {}", + toOrgId, + resp); + System.out.println( + "[checkAmopHealth] toOrgId -->" + toOrgId + " check failed. please check log."); + } + return resp.getErrorCode(); + }*/ +} diff --git a/src/main/java/com/webank/weid/config/ContractConfig.java b/src/main/java/com/webank/weid/config/ContractConfig.java index e38457ac..cbe461e4 100644 --- a/src/main/java/com/webank/weid/config/ContractConfig.java +++ b/src/main/java/com/webank/weid/config/ContractConfig.java @@ -1,50 +1,39 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.config; import lombok.Data; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; /** + * contract address config. + * * @author tonychen 2018.9.29 */ -@Component("ContractConfig") @Data public class ContractConfig { /** * The WeIdentity DID Contract address. */ - @Value("${weId.contractaddress}") private String weIdAddress; /** * The CPT Contract address. */ - @Value("${cpt.contractaddress}") private String cptAddress; /** * The AuthorityIssuerController Contract address. */ - @Value("${issuer.contractaddress}") private String issuerAddress; + + /** + * The EvidenceController Contract address. + */ + private String evidenceAddress; + + /** + * The Specific issuer Contract address. + */ + private String specificIssuerAddress; } diff --git a/src/main/java/com/webank/weid/constant/CptType.java b/src/main/java/com/webank/weid/constant/CptType.java new file mode 100644 index 00000000..390a8193 --- /dev/null +++ b/src/main/java/com/webank/weid/constant/CptType.java @@ -0,0 +1,59 @@ + + +package com.webank.weid.constant; + +/** + * CPT type enum. + * + * @author tonychen 2020年2月17日 + */ +public enum CptType { + + /** + * original type, used to create original type credential. + */ + ORIGINAL(0, "original"), + + /** + * zkp type, used to create zkp type credential. + */ + ZKP(1, "zkp"); + + /** + * type code. + */ + private Integer code; + /** + * type name. + */ + private String name; + + /** + * constructor. + * + * @param code cpt type code + * @param name cpt type name + */ + CptType(Integer code, String name) { + this.code = code; + this.name = name; + } + + /** + * get type code. + * + * @return type code + */ + public Integer getCode() { + return this.code; + } + + /** + * get type name. + * + * @return type name + */ + public String getName() { + return this.name; + } +} diff --git a/src/main/java/com/webank/weid/constant/CredentialConstant.java b/src/main/java/com/webank/weid/constant/CredentialConstant.java new file mode 100644 index 00000000..1e478745 --- /dev/null +++ b/src/main/java/com/webank/weid/constant/CredentialConstant.java @@ -0,0 +1,163 @@ + + +package com.webank.weid.constant; + +/** + * The Class CredentialConstant. + * + * @author chaoxinhu + */ + +public final class CredentialConstant { + + /** + * The Constant default Credential Context. + */ + public static final String DEFAULT_CREDENTIAL_CONTEXT = + "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1"; + + /** + * The Constant default Credential Context field name in Credential Json String. + */ + public static final String CREDENTIAL_CONTEXT_PORTABLE_JSON_FIELD = "@context"; + + /** + * The Constant default Credential type. + */ + public static final String DEFAULT_CREDENTIAL_TYPE = "VerifiableCredential"; + + /** + * cpt type. + */ + public static final String CPT_TYPE_KEY = "cptType"; + + /** + * The Constant selective Credential type. + */ + public static final String SELECTIVE_CREDENTIAL_TYPE = "hashTree"; + + /** + * The Constant is an field in PresentationPolicyE. + */ + public static final String CLAIM_POLICY_FIELD = "policy"; + + /** + * key id. + */ + public static final String ID = "id"; + + /** + * credential id. + */ + public static final String CREDENTIAL_META_KEY_ID = "credentialId"; + + /** + * The CPT type in standard integer format. + */ + public static final String CREDENTIAL_META_KEY_CPTID = "cptId"; + + /** + * The issuer WeIdentity DID. + */ + public static final String CREDENTIAL_META_KEY_ISSUER = "issuer"; + + /** + * The expire date. + */ + public static final String CREDENTIAL_META_KEY_EXPIRATIONDATE = "expirationDate"; + + /** + * The issuance date of the credential. + */ + public static final String CREDENTIAL_META_KEY_ISSUANCEDATE = "issuanceDate"; + + /** + * credential context. + */ + public static final String CREDENTIAL_META_KEY_CONTEXT = "context"; + + /** + * The Constant is an field in claimPolicy. + */ + public static final String CLAIM_POLICY_DISCLOSED_FIELD = "fieldsToBeDisclosed"; + /** + * Default CPT ID for embedded credential signature subject (multi-sign support). + */ + public static final Integer CREDENTIAL_EMBEDDED_SIGNATURE_CPT = 106; + /** + * Default CPT ID for embedded credentialPojo subject (multi-sign support). + */ + public static final Integer CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT = 107; + /** + * Embedded trusted timestamp default CPT ID. + */ + public static final Integer EMBEDDED_TIMESTAMP_CPT = 108; + /** + * Embedded trusted timestamp envelop default CPT ID. + */ + public static final Integer TIMESTAMP_ENVELOP_CPT = 109; + /** + * Authorization CPT ID. + */ + public static final Integer AUTHORIZATION_CPT = 101; + /** + * Challenge CPT ID. + */ + public static final Integer CHALLENGE_CPT = 102; + /** + * Challenge Verification CPT ID. + */ + public static final Integer CHALLENGE_VERIFICATION_CPT = 103; + /** + * Claim Policy CPT ID. + */ + public static final Integer CLAIM_POLICY_CPT = 104; + /** + * Service Endpoint CPT ID. + */ + public static final Integer SERVICE_ENDPOINT_CPT = 105; + + /** + * metadata CPT ID. + */ + public static final Integer METADATA_CPT = 110; + + /** + * metadata CPT ID. + */ + public static final Integer ZKP_USER_NONCE_CPT = 111; + + public static final String PRESENTATION_PDF = "presentationFromPDF"; + /** + * CPT key words. + */ + public static final String[] CPT_KEY_WORDS = {"GE", "LE", "GT", "LT", "EQ"}; + + /** + * The Credential Proof Type Enumerate. + */ + public static enum CredentialProofType { + ECDSA("Secp256k1"); + + /** + * The Type Name of the Credential Proof. + */ + private String typeName; + + /** + * Constructor. + */ + CredentialProofType(String typeName) { + this.typeName = typeName; + } + + /** + * Getter. + * + * @return typeName + */ + public String getTypeName() { + return typeName; + } + } +} diff --git a/src/main/java/com/webank/weid/constant/CredentialFieldDisclosureValue.java b/src/main/java/com/webank/weid/constant/CredentialFieldDisclosureValue.java new file mode 100644 index 00000000..8d5f136f --- /dev/null +++ b/src/main/java/com/webank/weid/constant/CredentialFieldDisclosureValue.java @@ -0,0 +1,44 @@ + + +package com.webank.weid.constant; + +/** + * credential field disclosure status. + * + * @author tonychen + */ +public enum CredentialFieldDisclosureValue { + + /** + * the field is existed. + */ + EXISTED(2), + + /** + * the field is disclosed. + */ + DISCLOSED(1), + + /** + * the field is not disclosed. + */ + NOT_DISCLOSED(0); + + /** + * disclosure status. + */ + private Integer status; + + CredentialFieldDisclosureValue(Integer status) { + this.status = status; + } + + /** + * get field disclosure status. + * + * @return disclosure status of the field. + */ + public Integer getStatus() { + return status; + } +} diff --git a/src/main/java/com/webank/weid/constant/CredentialType.java b/src/main/java/com/webank/weid/constant/CredentialType.java new file mode 100644 index 00000000..098d6f07 --- /dev/null +++ b/src/main/java/com/webank/weid/constant/CredentialType.java @@ -0,0 +1,64 @@ + + + +package com.webank.weid.constant; + +/** + * Credential type. + * @author tonychen 2020年4月22日 + */ +public enum CredentialType { + + /** + * original type, used to create original type credential. + */ + ORIGINAL(0, "original"), + + /** + * zkp type, used to create zkp type credential. + */ + ZKP(1, "zkp"), + + /** + * lite1 type, used to create lite1 type credential. + */ + LITE1(2, "lite1"); + + /** + * type code. + */ + private Integer code; + /** + * type name. + */ + private String name; + + /** + * constructor. + * + * @param code credential type code + * @param name credential type name + */ + CredentialType(Integer code, String name) { + this.code = code; + this.name = name; + } + + /** + * get type code. + * + * @return type code + */ + public Integer getCode() { + return this.code; + } + + /** + * get type name. + * + * @return type name + */ + public String getName() { + return this.name; + } +} diff --git a/src/main/java/com/webank/weid/constant/DataDriverConstant.java b/src/main/java/com/webank/weid/constant/DataDriverConstant.java new file mode 100644 index 00000000..c09d52ed --- /dev/null +++ b/src/main/java/com/webank/weid/constant/DataDriverConstant.java @@ -0,0 +1,320 @@ + + +package com.webank.weid.constant; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * constant for DataDriver. + * + * @author tonychen 2019年3月25日 + */ +public final class DataDriverConstant { + + /** + *encoding form. + */ + public static final Charset STANDARDCHARSETS_ISO = StandardCharsets.ISO_8859_1; + public static final Charset STANDARDCHARSETS_UTF_8 = StandardCharsets.UTF_8; + + + /** + * redis execute status. + */ + public static final int REDISSON_EXECUTE_FAILED_STATUS = 0; + public static final int REDISSON_EXECUTE_SUCESS_STATUS = 1; + + /** + * redis mode name. + */ + public static final String REDIS_SINGLE = "redis_single"; + public static final String REDIS_CLUSTER = "redis_cluster"; + + /** + * redis url properties. + */ + public static final String REDIS_URL = "redis.url"; + + /** + * redis user password properties. + */ + public static final String REDIS_PASSWORD = "redis.password"; + + /** + * redis single database properties. + */ + public static final String REDIS_DATABASE = "database"; + + /** + * redis cluster idle_connection_timeout properties. + */ + public static final String IDLE_CONNECTION_TIMEOUT = "idle_connection_timeout"; + + /** + * redis cluster connect_timeout properties. + */ + public static final String CONNECT_TIMEOUT = "connect_timeout"; + + /** + * redis cluster timeout properties. + */ + public static final String TIMEOUT = "timeout"; + + /** + * redis cluster slave_connection_minimum_idle_size properties. + */ + public static final String SLAVE_CONNECTION_MINIMUM_IDLE_SIZE = + "slave_connection_minimum_idle_size"; + + /** + * redis cluster slave_connection_pool_size properties. + */ + public static final String SLAVE_CONNECTION_POOL_SIZE = + "slave_connection_pool_size"; + + /** + * redis cluster master_connection_minimum_idle_size properties. + */ + public static final String MASTER_CONNECTION_MINIMUM_IDLE_SIZE = + "master_connection_minimum_idle_size"; + + /** + * redis cluster master_connection_pool_size properties. + */ + public static final String MASTER_CONNECTION_POOL_SIZE = + "master_connection_pool_size"; + + /** + * the default value for redis single config. + */ + public static final String DATABASE_DEFAULT_VALUE = "0"; + + /** + * the default value for redis cluster config. + */ + public static final String IDLE_CONNECTION_TIMEOUT_DEFAULT_VALUE = "10000"; + public static final String CONNECT_TIMEOUT_DEFAULT_VALUE = "10000"; + public static final String TIMEOUT_DEFAULT_VALUE = "3000"; + public static final String SLAVE_CONNECTION_MINIMUM_IDLE_SIZE_DEFAULT_VALUE = "10"; + public static final String SLAVE_CONNECTION_POOL_SIZE_DEFAULT_VALUE = "64"; + public static final String MASTER_CONNECTION_MINIMUM_IDLE_SIZE_DEFAULT_VALUE = "10"; + public static final String MASTER_CONNECTION_POOL_SIZE_DEFAULT_VALUE = "64"; + + /** + * jdbc url properties. + */ + public static final String JDBC_DATASOURCE_NAME = "datasource.name"; + + /** + * jdbc url properties. + */ + public static final String JDBC_URL = "jdbc.url"; + + /** + * jdbc driver properties. + */ + public static final String JDBC_DRIVER = "jdbc.driver"; + + /** + * jdbc username properties. + */ + public static final String JDBC_USER_NAME = "jdbc.username"; + + /** + * jdbc user password properties. + */ + public static final String JDBC_USER_PASSWORD = "jdbc.password"; + + /** + * jdbc maxActive properties. + */ + public static final String JDBC_MAX_ACTIVE = "jdbc.maxActive"; + + /** + * jdbc minIdle properties. + */ + public static final String JDBC_MIN_IDLE = "jdbc.minIdle"; + + /** + * jdbc maxIdle properties. + */ + public static final String JDBC_MAX_IDLE = "jdbc.maxIdle"; + + /** + * jdbc maxWait properties. + */ + public static final String JDBC_MAX_WAIT = "jdbc.maxWait"; + + /** + * jdbc timeBetweenEvictionRunsMillis properties. + */ + public static final String JDBC_TIME_BETWEEN_ERM = "jdbc.timeBetweenEvictionRunsMillis"; + + /** + * jdbc numTestsPerEvictionRun properties. + */ + public static final String JDBC_NUM_TEST_PER_ER = "jdbc.numTestsPerEvictionRun"; + + /** + * jdbc minEvictableIdleTimeMillis properties. + */ + public static final String JDBC_MIN_EITM = "jdbc.minEvictableIdleTimeMillis"; + + /** + * jdbc initialSize properties. + */ + public static final String JDBC_INIT_SIZE = "jdbc.initialSize"; + + /** + * jdbc driverClassName. + */ + public static final String JDBC_MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; + + /** + * jdbc removeAbandoned. + */ + public static final String JDBC_REMOVE_ABANDONED = "true"; + + /** + * jdbc removeAbandonedTimeout. + */ + public static final String JDBC_REMOVE_ABANDONED_TIMEOUT = "180"; + + /** + * jdbc testOnBorrow. + */ + public static final String JDBC_TEST_ON_BORROW = "false"; + + /** + * jdbc testOnWhile. + */ + public static final String JDBC_TEST_ON_WHILE = "true"; + + /** + * jdbc validationQuery. + */ + public static final String JDBC_VALIDATION_QUERY = "SELECT 1"; + + /** + * sql execute status. + */ + public static final int SQL_EXECUTE_FAILED_STATUS = 0; + + /** + * jdbc user password properties. + */ + public static final String SQL_COLUMN_DATA = "data"; + + /** + * sql index. + */ + public static final int SQL_INDEX_FIRST = 1; + + /** + * sql index. + */ + public static final int SQL_INDEX_SECOND = 2; + + /** + * sql index. + */ + public static final int SQL_INDEX_THIRD = 3; + + /** + * the key of ConnectionPool. + */ + public static final String POOL_DRIVER_CLASS_NAME = "driverClassName"; + public static final String POOL_URL = "url"; + public static final String POOL_USERNAME = "username"; + public static final String POOL_PASSWORD = "password"; + public static final String POOL_INITIAL_SIZE = "initialSize"; + public static final String POOL_MAX_ACTIVE = "maxTotal"; + public static final String POOL_MIN_IDLE = "minIdle"; + public static final String POOL_MAX_IDLE = "maxIdle"; + public static final String POOL_MAX_WAIT = "maxWaitMillis"; + public static final String POOL_MAX_REMOVE_ABANDONED = "removeAbandonedOnBorrow"; + public static final String POOL_MAX_REMOVE_MAINTENANCE = "removeAbandonedOnMaintenance"; + public static final String POOL_MAX_REMOVE_ABANDONED_TIMEOUT = "removeAbandonedTimeout"; + public static final String POOL_TEST_ON_BORROW = "testOnBorrow"; + public static final String POOL_TEST_ON_WHILE = "testWhileIdle"; + public static final String POOL_TIME_BETWEEN_ERM = "timeBetweenEvictionRunsMillis"; + public static final String POOL_NUM_TEST_PER_ER = "numTestsPerEvictionRun"; + public static final String POOL_VALIDATION_QUERY = "validationQuery"; + public static final String POOL_MIN_EITM = "minEvictableIdleTimeMillis"; + + /** + * the default value for pool. + */ + public static final String POOL_DRIVER_NAME_DEFAULT_VALUE = "com.mysql.jdbc.Driver"; + public static final String POOL_MAX_ACTIVE_DEFAULT_VALUE = "50"; + public static final String POOL_MIN_IDLE_DEFAULT_VALUE = "5"; + public static final String POOL_INIT_DEFAULT_VALUE = "5"; + public static final String POOL_MAX_IDLE_DEFAULT_VALUE = "5"; + public static final String POOL_MAX_WAIT_DEFAULT_VALUE = "10000"; + public static final String POOL_NUM_TEST_PER_ER_DEFAULT_VALUE = "5"; + public static final String POOL_TIME_BETWEEN_ERM_DEFAULT_VALUE = "600000"; + public static final String POOL_MIN_EITM_DEFAULT_VALUE = "1800000"; + + /** + * 系统默认的domain. + */ + public static final String DOMAIN_DEFAULT_INFO = "domain.defaultInfo"; + public static final String DOMAIN_DEFAULT_INFO_TIMEOUT = "domain.defaultInfo.timeout"; + + /** + * redis存储的离线交易记录. + */ + public static final String DOMAIN_OFFLINE_TRANSACTION_INFO = "offline_transaction_info"; + + /** + * 系统domain之私钥存储domainKey. + */ + public static final String DOMAIN_ENCRYPTKEY = "domain.encryptKey"; + + public static final String DOMAIN_ISSUER_TEMPLATE_SECRET = "domain.templateSecret"; + + public static final String DOMAIN_USER_MASTER_SECRET = "domain.masterKey"; + + public static final String DOMAIN_USER_CREDENTIAL_SIGNATURE = "domain.credentialSignature"; + + public static final String DOMAIN_RESOURCE_INFO = "domain.resourceInfo"; + + public static final String DOMAIN_WEID_AUTH = "domain.weIdAuth"; + + /** + * 本地运行所需表. + */ + + public static final String LOCAL_WEID_DOCUMENT = "local.weIdDocument"; + + public static final String LOCAL_CPT = "local.cpt"; + + public static final String LOCAL_POLICY = "local.policy"; + + public static final String LOCAL_PRESENTATION = "local.presentation"; + + public static final String LOCAL_ROLE = "local.role"; + + public static final String LOCAL_AUTHORITY_ISSUER = "local.authorityIssuer"; + + public static final String LOCAL_SPECIFIC_ISSUER = "local.specificIssuer"; + + public static final String LOCAL_EVIDENCE = "local.evidence"; + + /** + * ipfs所需常量. + */ + public static final int IPFS_EXECUTE_FAILED_STATUS = 0; + + public static final String IPFS_API ="ipfs.api"; + + public static final String IPFS_BASE_PATH ="output/local/"; + + public static final int IPFS_WRITE_SUCCESS = 0; + + public static final int IPFS_ONLY_ID_LINES = 1; + + public static final int IPFS_READ_CID_LINES = 2; + +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/constant/ErrorCode.java b/src/main/java/com/webank/weid/constant/ErrorCode.java index b14e677d..f63f5caa 100644 --- a/src/main/java/com/webank/weid/constant/ErrorCode.java +++ b/src/main/java/com/webank/weid/constant/ErrorCode.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.constant; @@ -31,62 +14,82 @@ public enum ErrorCode { */ SUCCESS(0, "success"), + /** + * No Permission to perform contract level tasks. + */ + CONTRACT_ERROR_NO_PERMISSION( + 500000, + "contract error: no permission to perform this task" + ), + /** * The cpt not exists. */ CPT_NOT_EXISTS(500301, "cpt does not exist"), /** - * cpt id generated for authority issuer exceeds limited max value + * cpt id generated for authority issuer exceeds limited max value. */ CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX( - 500302, "cpt id generated for authority issuer exceeds limited max value"), + 500302, + "cpt id generated for authority issuer exceeds limited max value" + ), /** - * cpt publisher does not exist + * cpt publisher does not exist. */ CPT_PUBLISHER_NOT_EXIST(500303, "cpt publisher does not exist"), + /** + * This cpt id already exists on chain. + */ + CPT_ALREADY_EXIST(500304, "cpt already exist on chain"), + + /** + * No permission to perform this CPT task. + */ + CPT_NO_PERMISSION(500305, "no permission to perform this cpt task"), + /** * The cpt json schema invalid. */ CPT_JSON_SCHEMA_INVALID(100301, "cpt json schema is invalid"), /** - * Credential main error code. + * cptId illegal. */ - CREDENTIAL_ERROR(100400, "error occured during processing credential tasks"), + CPT_ID_ILLEGAL(100303, "cptId illegal"), /** - * The exact error codes in credential tasks. + * cpt event log is null. */ - CREDENTIAL_NOT_EXISTS(100401, "credential does not exist"), + CPT_EVENT_LOG_NULL(100304, "cpt event log is null."), /** - * The credential expired. + * credential template save failed. */ - CREDENTIAL_EXPIRED(100402, "credential is expired"), + CPT_CREDENTIAL_TEMPLATE_SAVE_ERROR(100305, "cpt credential template saved with error."), /** - * The credential issuer mismatch. + * Credential main error code. */ - CREDENTIAL_ISSUER_MISMATCH(100403, "credential issuer does not match the signature"), + CREDENTIAL_ERROR(100400, "error occured during processing credential tasks"), /** - * The credential issuer not exists in list. + * The credential expired. */ - CREDENTIAL_ISSUER_NOT_EXISTS_IN_LIST( - 100404, "credential issuer does not exist in the authority issuer list"), + CREDENTIAL_EXPIRED(100402, "credential is expired"), /** - * The credential signature broken. + * The credential issuer mismatch. */ - CREDENTIAL_SIGNATURE_BROKEN(100405, "credential signature cannot be extracted"), + CREDENTIAL_ISSUER_MISMATCH(100403, + "issuer (signer) weId does not match the weId of credential"), /** - * The credential revoked. + * The credential signature broken. */ - CREDENTIAL_REVOKED(100406, "credential is revoked"), + CREDENTIAL_SIGNATURE_BROKEN(100405, "credential signature cannot be extracted"), /** * The credential issuer not exists. @@ -94,9 +97,9 @@ public enum ErrorCode { CREDENTIAL_ISSUER_NOT_EXISTS(100407, "credential issuer does not exist"), /** - * The credential create date illegal. + * The credential issuance date illegal. */ - CREDENTIAL_CREATE_DATE_ILLEGAL(100408, "create date illegal"), + CREDENTIAL_ISSUANCE_DATE_ILLEGAL(100408, "credential issuance date illegal"), /** * The credential expire date illegal. @@ -123,6 +126,11 @@ public enum ErrorCode { */ CREDENTIAL_CONTEXT_NOT_EXISTS(100413, "credential context does not exist"), + /** + * The credential type is null. + */ + CREDENTIAL_TYPE_IS_NULL(100414, "credential type is null"), + /** * The credential private key not exists. */ @@ -137,38 +145,418 @@ public enum ErrorCode { * The credential issuer does not have a valid WeIdentity DID document. */ CREDENTIAL_WEID_DOCUMENT_ILLEGAL(100417, "weid document illegal"), - + /** * The credential issuer is invalid. */ - CREDENTIAL_ISSUER_INVALID(100418, "credential issuer invalid"), + CREDENTIAL_ISSUER_INVALID(100418, "credential issuer invalid or mismatch the WeID auth"), /** - * Authority issuer main error code. + * The credential credential verify signature is exception. */ - AUTHORITY_ISSUER_ERROR(100200, "error occured during processing authority issuer tasks"), + CREDENTIAL_EXCEPTION_VERIFYSIGNATURE(100419, "credential verify signature exception"), /** - * The authority issuer argument not exists. + * claim policy is null. */ - AUTHORITY_ISSUER_ARGUMENT_NOT_EXISTS(100201, "the argument passed in is null"), + CREDENTIAL_CLAIM_POLICY_NOT_EXIST(100420, "claim policy is null"), /** - * The authority issuer private key param is illegal. + * The credential private key not exists. */ - AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL(100202, "the private key is illegal"), + CREDENTIAL_PUBLIC_KEY_NOT_EXISTS( + 100421, + "public key for verifying credential signature does not exist" + ), + + /** + * The signature for verifying credential does not exist. + */ + CREDENTIAL_SIGNATURE_NOT_EXISTS(100422, "signature for verifying credential does not exist"), + + /** + * The credential policy disclosurevalue illegal. + */ + CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL(100423, "policy disclosurevalue illegal"), + + /** + * The credential disclosurevalue notmatch saltvalue. + */ + CREDENTIAL_DISCLOSUREVALUE_NOTMATCH_SALTVALUE(100424, "disclosurevalue notmatch saltvalue"), + + /** + * The credential cptId notmatch. + */ + CREDENTIAL_CPTID_NOTMATCH(100425, "credential cptId notmatch"), + + /** + * The credential presenterWeId notmatch. + */ + CREDENTIAL_PRESENTERWEID_NOTMATCH(100426, "credential presenter WeId not match"), + + /** + * The credential evidence id mismatch. + */ + CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM( + 100427, + "credential disclosure format does not match claim" + ), /** - * The authority issuer address mismatch. + * credential disclosure data illegal. */ - AUTHORITY_ISSUER_ADDRESS_MISMATCH(100204, - "address in event log does not match the WeIdentity DID"), + CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL(100428, "credential disclosure data illegal"), + + /** + * The credential signature broken. + */ + CREDENTIAL_SIGNATURE_TYPE_ILLEGAL(100429, "credential signature type unknown"), + + /** + * credential salt illegal. + */ + CREDENTIAL_SALT_ILLEGAL(100430, "credential salt illegal"), + + /** + * credential evidence cannot be extracted. + */ + CREDENTIAL_EVIDENCE_SIGNATURE_BROKEN(100431, "credential evidence cannot be extracted"), + + /** + * credential has already been disclosed once. + */ + CREDENTIAL_RE_DISCLOSED(100432, + "credential has already been disclosed once, can not be re-disclosed"), + + /** + * Timestamp service error. + */ + TIMESTAMP_SERVICE_BASE_ERROR(100433, "timestamp service error"), + + /** + * System CPT Claim verification failure. + */ + CREDENTIAL_SYSTEM_CPT_CLAIM_VERIFY_ERROR(100434, "external credential verify" + + " succeeded, but inner content verify failed"), + + /** + * Timestamp service unavailable. + */ + TIMESTAMP_SERVICE_UNCONFIGURED(100435, "timestamp service not configured"), + + /** + * Timestamp service: WeSign workflow error. + */ + TIMESTAMP_SERVICE_WESIGN_ERROR(100436, "wesign timestamp service error: check log for details"), + + /** + * Timestamp verification failed. + */ + TIMESTAMP_VERIFICATION_FAILED(100437, "timestamp verification failed"), + + /** + * Timestamp service does not support selectively-disclosed credential's presence. + */ + TIMESTAMP_CREATION_FAILED_FOR_SELECTIVELY_DISCLOSED(100438, + "timestamp creation does not support selectively disclosed credential"), + + CREDENTIAL_USE_VERIFY_FUNCTION_ERROR(100439, + "presentation from pdf transportation, please use verifyPresentationFromPDF function"), + + /** + * the error code shows that the credential passed in the function is not supported by this + * function. + */ + CREDENTIAL_NOT_SUPPORT_SELECTIVE_DISCLOSURE(100440, + "the error code shows that the credential passed in the " + + "function is not supported by this function."), + + /** + * credential verify fail. + */ + CREDENTIAL_VERIFY_FAIL(100441, "credential verify fail."), + + /** + * credential verify succeeded with a wrong public key ID. + */ + CREDENTIAL_VERIFY_SUCCEEDED_WITH_WRONG_PUBLIC_KEY_ID(100442, "credential" + + "verify succeeded, but the given public key ID is incorrect."), + + /** + * credential is disclosed. + */ + CREDENTIAL_IS_DISCLOSED(100443, "credential is disclosed."), + + /** + * credential does not match CPT. + */ + CREDENTIAL_DOES_NOT_MATCHE_THE_CPT(100444, "credential does not match CPT."), + + /** + * Authorization WeIDs: from and to must be different. + */ + AUTHORIZATION_FROM_TO_MUST_BE_DIFFERENT(100450, + "authorization's fromWeId and toWeId must be different" + ), + + /** + * Authorization: cannot authorize other WeID's resource. + */ + AUTHORIZATION_CANNOT_AUTHORIZE_OTHER_WEID_RESOURCE(100451, + "cannot authorize other WeID's resource" + ), + + /** + * The credential evidence contract failure: illegal input. + */ + CREDENTIAL_EVIDENCE_CONTRACT_FAILURE_ILLEAGAL_INPUT( + 500401, + "credential evidence contract failure: illegal input." + ), + + /** + * The credential evidence base error. + */ + CREDENTIAL_EVIDENCE_BASE_ERROR( + 100500, + "generic error when processing credential evidence tasks" + ), + + /** + * The credential evidence hash mismatch. + */ + CREDENTIAL_EVIDENCE_HASH_MISMATCH(100501, "evidence hash mismatch"), + + /** + * The credential evidence does not exist on chain. + */ + CREDENTIAL_EVIDENCE_NOT_EXIST(100502, "evidence does not exist on chain"), + + /** + * The credential evidence already exists on chain. + */ + CREDENTIAL_EVIDENCE_ALREADY_EXISTS(100503, "evidence already exists on chain"), + + /** + * The credential evidence interface does not support fisco bcos 1.3. + */ + FISCO_BCOS_VERSION_NOT_SUPPORTED(170000, + "this function does not support current fisco bcos version"), + + /** + * On-chain string length exceeded acceptable max. + */ + ON_CHAIN_STRING_TOO_LONG(100504, "on-chain String length exceeds limit"), + + /** + * offline evidence transaction saved failed. + */ + OFFLINE_EVIDENCE_SAVE_FAILED(100505, "offline evidence transaction saved failed."), + + /** + * The challenge is invalid. + */ + PRESENTATION_CHALLENGE_INVALID(100600, "the challenge is invalid."), + + /** + * The weId of challenge does not match the user's weId. + */ + PRESENTATION_CHALLENGE_WEID_MISMATCH( + 100601, + "the weId of challenge does not match the user's weId." + ), + + /** + * The presentation policy is invalid. + */ + PRESENTATION_POLICY_INVALID(100602, "the presentation policy is invalid."), + + /** + * the credentialList of presentation don't match the claim policy. + */ + PRESENTATION_CREDENTIALLIST_MISMATCH_CLAIM_POLICY( + 100603, + "the credentiallist of presentation don't match the claim policy." + ), + + /** + * the authentication method id is invalid. + */ + PRESENTATION_AUTHENTICATION_METHOD_ID_INVALID(100604, "the authentication method id is invalid."), + + /** + * the nonce of challenge does not match the nonce of presentation. + */ + PRESENTATION_CHALLENGE_NONCE_MISMATCH( + 100605, + "the nonce of challenge does not match the nonce of presentation." + ), + + /** + * the signature of presentation does not match the presenter. + */ + PRESENTATION_SIGNATURE_MISMATCH( + 100606, + "the signature of presentation does not match the presenter." + ), + + /** + * the presenter weid of presentation does not match the credential. + */ + PRESENTATION_WEID_CREDENTIAL_WEID_MISMATCH( + 100607, + "the presenter weid of presentation does not match the credential." + ), + + /** + * the weid of the claim of the presentation does not exist. + */ + PRESENTATION_CREDENTIAL_CLAIM_WEID_NOT_EXIST( + 100608, + "the weid of the claim of the presentation does not exist." + ), + + /** + * the publisherWeId of policy is invalid. + */ + PRESENTATION_POLICY_PUBLISHER_WEID_INVALID( + 100609, + "the publisherWeId of policy is invalid." + ), + + /** + * the publisherWeId of policy does not exist. + */ + PRESENTATION_POLICY_PUBLISHER_WEID_NOT_EXIST( + 100610, + "the publisherWeId of policy does not exist." + ), + + /** + * the encrypt key is not exists. + */ + ENCRYPT_KEY_NOT_EXISTS(100700, "the encrypt key not exists."), + + /** + * the policy service is not exists. + */ + POLICY_SERVICE_NOT_EXISTS(100701, "no policy service."), + + /** + * the policy service call fail. + */ + POLICY_SERVICE_CALL_FAIL(100702, "the policy service call fail, please check the error log."), + + /** + * the policy service call fail. + */ + ENCRYPT_KEY_NO_PERMISSION(100703, "no permission to get the key."), + + /** + * the key is invalid. + */ + ENCRYPT_KEY_INVALID(100704, "the key is invalid."), + + /** + * encrypt data failed. + */ + ENCRYPT_DATA_FAILED(100705, "encrypt data failed."), + + /** + * decrypt data failed. + */ + DECRYPT_DATA_FAILED(100706, "decrypt data failed."), + + /** + * transportation base error. + */ + TRANSPORTATION_BASE_ERROR(100800, "suite baes exception error, please check the error log."), + + /** + * transportation protocol error. + */ + TRANSPORTATION_PROTOCOL_PROPERTY_ERROR(100801, "the protocol property is error."), + + /** + * transportation protocol version error. + */ + TRANSPORTATION_PROTOCOL_VERSION_ERROR(100802, "the protocol version is error."), + + /** + * transportation protocol encode error. + */ + TRANSPORTATION_PROTOCOL_ENCODE_ERROR(100803, "the protocol encode is error."), + + /** + * transportation protocol value error. + */ + TRANSPORTATION_PROTOCOL_STRING_INVALID(100804, "the protocol string is invalid."), + + /** + * transportation protocol data error. + */ + TRANSPORTATION_PROTOCOL_DATA_INVALID(100805, "the protocol data is invalid."), + + /** + * transportation protocol field invalid. + */ + TRANSPORTATION_PROTOCOL_FIELD_INVALID( + 100806, + "the protocol field value invalid." + ), + + /** + * transportation protocol encode error. + */ + TRANSPORTATION_ENCODE_BASE_ERROR(100807, "encode base error, please check the error log."), + + /** + * pdf transfer error. + */ + TRANSPORTATION_PDF_TRANSFER_ERROR(100808, "pdf transfer error, please check the error log."), + + /** + * pdf transfer error. + */ + TRANSPORTATION_PDF_VERIFY_ERROR(100809, "pdf verify error, please check the error log."), + + /** + * the transmission type is invalid. + */ + TRANSPORTATION_TRANSMISSION_TYPE_INVALID(100810, "the trans type is invalid."), + + /** + * the URI type is invalid. + */ + TRANSPORTATION_URI_TYPE_INVALID(100811, "the URI type is invalid."), + + /** + * no spcifyer to set. + */ + TRANSPORTATION_NO_SPECIFYER_TO_SET(100812, "no spcifyer to set."), + + /** + * the trans mode is invalid. + */ + TRANSPORTATION_TRANSMODE_TYPE_INVALID(100813, "the trans mode is invalid."), + + /** + * Authority issuer main error code. + */ + AUTHORITY_ISSUER_ERROR(100200, "error occured during processing authority issuer tasks"), + + /** + * The authority issuer private key param is illegal. + */ + AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL(100202, "the private key is illegal"), /** * The authority issuer opcode mismatch. */ - AUTHORITY_ISSUER_OPCODE_MISMATCH(100205, - "opcode in event log does not match the desired opcode"), + AUTHORITY_ISSUER_OPCODE_MISMATCH( + 100205, + "opcode in event log does not match the desired opcode" + ), /** * The authority issuer name illegal. @@ -179,25 +567,123 @@ public enum ErrorCode { * The authority issuer accvalue illegal. */ AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL( - 100207, "the authority issuer accumulator value is illegal (integer value required)"), + 100207, + "the authority issuer accumulator value is illegal (integer value required)" + ), + + /** + * The specific issuer type illegal. + */ + SPECIFIC_ISSUER_TYPE_ILLEGAL( + 100208, + "the specific issuer type is illegal" + ), + + AUTORITY_ISSUER_DESCRIPTION_ILLEGAL( + 100209, + "authority issuer description illegal" + ), + + AUTHORITY_ISSUER_EXTRA_PARAM_ILLEGAL( + 100210, + "authority issuer extra param illegal" + ), + + /** + * the key of the data is empty. + */ + PRESISTENCE_DATA_KEY_INVALID( + 100901, + "the key of the data is empty." + ), + + /** + * the domain is illegal. + */ + PRESISTENCE_DOMAIN_ILLEGAL( + 100902, + "the domain is illegal." + ), /** - * The Authority Issuer Contract level error: subject already exists + * the domain is illegal. + */ + PRESISTENCE_DOMAIN_INVALID( + 100903, + "the domain is invalid." + ), + + /** + * the data does not match for batch save. + */ + PERSISTENCE_BATCH_ADD_DATA_MISMATCH( + 100904, + "the data does not match for batch add." + ), + + /** + * The Authority Issuer Contract level error: subject already exists. */ AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST( - 500201, "the authority issuer contract error: the subject already exists"), + 500201, + "the authority issuer contract error: the subject already exists" + ), /** - * The Authority Issuer Contract level error: subject already exists + * The Authority Issuer Contract level error: subject already exists. */ AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS( - 500202, "the authority issuer contract error: the subject does not exist"), + 500202, + "the authority issuer contract error: the subject does not exist" + ), + + /** + * The Authority Issuer Contract level error: name already exists. + */ + AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS( + 500203, + "the authority issuer name already exists." + ), + + /** + * The issuer is not recognized. + */ + AUTHORITY_ISSUER_CONTRACT_ERROR_UNRECOGNIZED( + 500204, + "this issuer has not been recognized yet." + ), + + /** + * The Specific Issuer Contract level error: already exists. + */ + SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS( + 500501, + "the specific issuer type or address already exists." + ), + + /** + * The Specific Issuer Contract level error: already exists. + */ + SPECIFIC_ISSUER_CONTRACT_ERROR_NOT_EXIST( + 500502, + "the specific issuer type or address does not exist." + ), /** - * The Authority Issuer Contract level error: no permission + * The capacity has reached the upper limit. */ - AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION( - 500203, "the authority issuer contract error: no permission"), + SPECIFIC_ISSUER_CONTRACT_ERROR_EXCEED_MAX( + 500503, + "the capacity has reached the upper limit." + ), + + /** + * Has issuer in the specific issuer type. + */ + SPECIFIC_ISSUER_CONTRACT_ERROR_EXIST_ISSUER( + 500504, + "has issuer in the specific issuer type." + ), /** * The weid invalid. @@ -210,36 +696,140 @@ public enum ErrorCode { WEID_PUBLICKEY_INVALID(100102, "the input public key is invalid."), /** - * private key is invalid + * private key is invalid. */ WEID_PRIVATEKEY_INVALID( - 100103, "the input private key is invalid, please check and input your private key."), + 100103, + "the input private key is invalid, please check and input your private key." + ), /** - * weid does not exist + * weid does not exist. */ WEID_DOES_NOT_EXIST(100104, "the weid does not exist on blockchain."), /** - * weid has already exist + * weid has already exist. */ WEID_ALREADY_EXIST(100105, "the weid has already exist on blockchain."), /** - * the private key is not the weid's + * the private key is not the weid's. */ WEID_PRIVATEKEY_DOES_NOT_MATCH(100106, "the private key does not match the current weid."), /** * create keypair exception. */ - WEID_KEYPAIR_CREATE_FAILED(10107, "create keypair faild."), + WEID_KEYPAIR_CREATE_FAILED(100107, "create keypair faild."), /** - * public key and private key are not a keypair + * public key and private key are not a keypair. */ WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED( - 10108, "the public key and private key are not matched."), + 100108, + "the public key and private key are not matched." + ), + + /** + * the authority of the weIdentity DID is invalid. + */ + WEID_AUTHORITY_INVALID(100109, "the authority of the weIdentity DID is invalid."), + + /** + * the length of the setService type is overlimit. + */ + WEID_SERVICE_TYPE_OVERLIMIT( + 100110, "the length of service type is overlimit." + ), + + /** + * you cannot remove your last public key or your own public key. + */ + WEID_CANNOT_REMOVE_ITS_OWN_PUB_KEY_WITHOUT_BACKUP( + 100111, + "cannot remove this WeID's owner or last public key without an available backup." + ), + + /** + * no permission of weIdAuth. + */ + WEID_AUTH_NO_PERMISSION( + 100112, + "no permission of weIdAuth." + ), + + /** + * no permission of weIdAuth. + */ + WEID_AUTH_NO_CALLBACK( + 100113, + "weIdAuth callback is not registered." + ), + + /** + * the channelId is null. + */ + WEID_AUTH_CHANNELID_IS_NULL( + 100114, + "the channelId is null." + ), + + /** + * the channelId is invalid. + */ + WEID_AUTH_CHANNELID_INVALID( + 100115, + "the channelId is invalid." + ), + + /** + * weid has been deactivated. + */ + WEID_HAS_BEEN_DEACTIVATED( + 100116, + "weid has been deactivated." + ), + + /** + * weid pubkey does not exist, used in revoke case. + */ + WEID_PUBLIC_KEY_NOT_EXIST( + 100117, + "this public key does not exist, or is already revoked." + ), + + /** + * Authentication with PublicKeyMultibase exists. + */ + AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS( + 100118, + "the Authentication with PublicKeyMultibase exists." + ), + + /** + * Authentication with method id exists. + */ + AUTHENTICATION_METHOD_ID_EXISTS( + 100119, + "the Authentication with method id exists." + ), + + /** + * Authentication method not exists. + */ + AUTHENTICATION_METHOD_NOT_EXISTS( + 100120, + "the Authentication method not exists." + ), + + /** + * Authentication with method id exists. + */ + SERVICE_METHOD_ID_EXISTS( + 100121, + "the service with id exists." + ), /** * transaction timeout. @@ -247,12 +837,12 @@ public enum ErrorCode { TRANSACTION_TIMEOUT(160001, "the transaction is timeout."), /** - * exception happens when transaction executes + * exception happens when transaction executes. */ TRANSACTION_EXECUTE_ERROR(160002, "the transaction does not correctly executed."), /** - * input parameter is illegal + * input parameter is illegal. */ ILLEGAL_INPUT(160004, "input parameter is illegal."), @@ -269,20 +859,99 @@ public enum ErrorCode { /** * weidentity base exceptions or error. */ - BASE_ERROR(160007, "baes exception error, please check error log."), + BASE_ERROR(160007, "base exception error, please check the error log."), + + /** + * weidentity data type case exceptions or error. + */ + DATA_TYPE_CASE_ERROR(160008, "data type cast exception error, please check the error log."), + + DIRECT_ROUTE_REQUEST_TIMEOUT(160009, "amop timeout"), + DIRECT_ROUTE_MSG_BASE_ERROR(160010, "amop response messageBody error."), + + /** + * persistence execute failed. + */ + PERSISTENCE_EXECUTE_FAILED(160011, "persistence execute failed."), + + /** + * AMOP server side has no direct route callback. + */ + AMOP_MSG_CALLBACK_SERVER_SIDE_NO_HANDLE( + 160012, + "amop server side has no direct route callback." + ), + + /** + * can not get the connection from pool. + */ + PERSISTENCE_GET_CONNECTION_ERROR( + 160013, + "can not get the connection from pool, please check the error log." + ), + + /** + * the orgid is null. + */ + ORG_ID_IS_NULL(160014, "the orgid is null."), + + /** + * the data is expire. + */ + PERSISTENCE_DATA_EXPIRE(160015, "the data is expire."), + + /** + * no premission. + */ + CNS_NO_PERMISSION(160016, "no premission for this cns."), + + /** + * the cns does not exist. + */ + CNS_DOES_NOT_EXIST(160017, "the cns does not exist."), + + /** + * the cns is used. + */ + CNS_IS_USED(160018, "the cns is used."), + + /** + * the cns is not used. + */ + CNS_IS_NOT_USED(160019, "the cns is not used."), + + /** + * the code is undefined. + */ + CNS_CODE_UNDEFINED(160020, "the code is undefined."), + + /** + * the data does not exist. + */ + PERSISTENCE_DATA_DOES_NOT_EXIST(160021, "the data does not exist."), + + /** + * this is unsupported. + */ + THIS_IS_UNSUPPORTED(160022, "this is unsupported."), + + /** + * this is repeated call. + */ + THIS_IS_REPEATED_CALL(160023, "this is repeated call."), /** * other uncatched exceptions or error. */ - UNKNOW_ERROR(160003, "unknow error, please check error log."); + UNKNOW_ERROR(160003, "unknow error, please check the error log."); /** - * error code + * error code. */ private int code; /** - * error message + * error message. */ private String codeDesc; @@ -297,6 +966,21 @@ public enum ErrorCode { this.codeDesc = codeDesc; } + /** + * get ErrorType By errcode. + * + * @param errorCode the ErrorCode + * @return errorCode + */ + public static ErrorCode getTypeByErrorCode(int errorCode) { + for (ErrorCode type : ErrorCode.values()) { + if (type.getCode() == errorCode) { + return type; + } + } + return ErrorCode.UNKNOW_ERROR; + } + /** * Get the Error Code. * @@ -311,7 +995,7 @@ public int getCode() { * * @param code the new ErrorCode */ - public void setCode(int code) { + protected void setCode(int code) { this.code = code; } @@ -329,7 +1013,7 @@ public String getCodeDesc() { * * @param codeDesc the new ErrorCode Description */ - public void setCodeDesc(String codeDesc) { + protected void setCodeDesc(String codeDesc) { this.codeDesc = codeDesc; } } diff --git a/src/main/java/com/webank/weid/constant/JsonSchemaConstant.java b/src/main/java/com/webank/weid/constant/JsonSchemaConstant.java new file mode 100644 index 00000000..22e280ec --- /dev/null +++ b/src/main/java/com/webank/weid/constant/JsonSchemaConstant.java @@ -0,0 +1,70 @@ +package com.webank.weid.constant; + +/** + * JsonSchema propertites. + * + * @author darwindu + */ +public final class JsonSchemaConstant { + + /** + * json schema: $schema key. + **/ + public static final String SCHEMA_KEY = "$schema"; + + /** + * json schema: $schema value. + **/ + public static final String SCHEMA_VALUE = "http://json-schema.org/draft-04/schema#"; + + /** + * json schema: type key. + **/ + public static final String TYPE_KEY = "type"; + + /** + * json schema: data type object. + **/ + public static final String DATA_TYPE_OBJECT = "object"; + + /** + * json schema: data type string. + **/ + public static final String DATA_TYPE_STRING = "string"; + + /** + * json schema: data type number. + **/ + public static final String DATA_TYPE_NUMBER = "number"; + + /** + * json schema: data type enum. + **/ + public static final String DATA_TYPE_ENUM = "enum"; + + /** + * json schema: title. + **/ + public static final String TITLE_KEY = "title"; + + /** + * json schema: description. + **/ + public static final String DESCRIPTION_KEY = "description"; + + /** + * json schema: properties. + **/ + public static final String PROPERTIES_KEY = "properties"; + + /** + * json schema: required. + **/ + public static final String REQUIRED_KEY = "required"; + + /** + * json schema: $schema key. + **/ + public static final String ADDITIONAL_PROPERTIES = "additionalProperties"; + +} diff --git a/src/main/java/com/webank/weid/constant/ParamKeyConstant.java b/src/main/java/com/webank/weid/constant/ParamKeyConstant.java new file mode 100644 index 00000000..d79490a3 --- /dev/null +++ b/src/main/java/com/webank/weid/constant/ParamKeyConstant.java @@ -0,0 +1,96 @@ + + +package com.webank.weid.constant; + +/** + * Define param key names to be allowed to enable calls to Java SDK. + * + * @author chaoxinhu + */ +public final class ParamKeyConstant { + + /** + * Universal param key names. + */ + public static final String WEID = "weId"; + + /** + * WeIdService related param names. + */ + public static final String PUBLIC_KEY = "publicKey"; + + /** + * AuthorityIssuer related param names. + */ + public static final String AUTHORITY_ISSUER_NAME = "name"; + + /** + * UTF-8. + */ + public static final String UTF_8 = "UTF-8"; + + /** + * CptService related param names. + */ + public static final String CPT_JSON_SCHEMA = "cptJsonSchema"; + public static final String CPT_SIGNATURE = "cptSignature"; + public static final String CPT = "Cpt"; + + /** + * CredentialService related param names. + */ + public static final String CPT_ID = "cptId"; + public static final String ISSUER = "issuer"; + public static final String CLAIM = "claim"; + public static final String EXPIRATION_DATE = "expirationDate"; + public static final String CREDENTIAL_SIGNATURE = "signature"; + public static final String CONTEXT = "context"; + public static final String CREDENTIAL_ID = "id"; + public static final String ISSUANCE_DATE = "issuanceDate"; + public static final String POLICY = "Policy"; + public static final String POLICY_PACKAGE = "com.webank.weid.cpt.policy."; + + /** + * proof key. + */ + public static final String PROOF = "proof"; + public static final String PROOF_SIGNATURE = "signatureValue"; + public static final String PROOF_TYPE = "type"; + public static final String PROOF_CREATED = "created"; + public static final String PROOF_CREATOR = "creator"; + public static final String PROOF_SALT = "salt"; + public static final String PROOF_VERIFICATION_METHOD_ID = "verificationMethodId"; + public static final String PROOF_NONCE = "nonce"; + public static final String PROOF_VERIFICATIONREQUEST = "verificationRequest"; + public static final String PROOF_ENCODEDVERIFICATIONRULE = "encodedVerificationRule"; + + + /** + * 秘钥存储KEY. + */ + public static final String KEY_DATA = "keyData"; + public static final String KEY_VERIFIERS = "verifiers"; + public static final String KEY_EXPIRE = "expirationDate"; + public static final String MASTER_SECRET = "masterSecret"; + public static final String BLINDING_FACTORS = "credentialSecretsBlindingFactors"; + + public static final String WEID_AUTH_OBJ = "weIdAuthObj"; + public static final String WEID_AUTH_SIGN_DATA = "signData"; + public static final String WEID_AUTH_CHALLENGE = "challenge"; + + public static final String TRNSACTION_RECEIPT_STATUS_SUCCESS = "0x0"; + public static final Integer TRNSACTION_RECEIPT_STATUS_SUCCESS_V3 = 0; + + /** + * 内置配置Key. + */ + public static final String RSYNC_IP = "rsyncIp"; + public static final String RSYNC_PORT = "rsyncPort"; + public static final String RSYNC_USER = "rsyncUser"; + public static final String RSYNC_PWD_NAME = "rsyncPwdName"; + public static final String RSYNC_BIN_LOG_MODULE = "binLog"; + public static final String BIN_LOG_PATH = "binLogPath"; + public static final String ENABLE_OFFLINE = "enableOffLine"; + public static final String INTEVAL_PERIOD = "inteval_period"; + public static final String SHARE_CNS = "cns.contract.share.follow."; +} diff --git a/src/main/java/com/webank/weid/constant/ProcessingMode.java b/src/main/java/com/webank/weid/constant/ProcessingMode.java new file mode 100644 index 00000000..7c7c8c9e --- /dev/null +++ b/src/main/java/com/webank/weid/constant/ProcessingMode.java @@ -0,0 +1,21 @@ + + +package com.webank.weid.constant; + +/** + * 上链处理模式. + * @author v_wbgyang + * + */ +public enum ProcessingMode { + + /** + * 立即上链模式,此模式下会立即将数据发送至区块链节点. + */ + IMMEDIATE, + + /** + * 批量延迟上链模式,此模式下会先将数据存入介质中,然后异步去上链处理. + */ + PERIODIC_AND_BATCH +} diff --git a/src/main/java/com/webank/weid/constant/ResolveEventLogStatus.java b/src/main/java/com/webank/weid/constant/ResolveEventLogStatus.java new file mode 100644 index 00000000..ccddb8ea --- /dev/null +++ b/src/main/java/com/webank/weid/constant/ResolveEventLogStatus.java @@ -0,0 +1,20 @@ +package com.webank.weid.constant; + +public enum ResolveEventLogStatus { + + STATUS_SUCCESS(0), + STATUS_EVENTLOG_NULL(-1), + STATUS_RES_NULL(-2), + STATUS_KEY_NOT_MATCH(-3), + STATUS_EVENT_NULL(-4); + + private Integer value; + + ResolveEventLogStatus(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/src/main/java/com/webank/weid/constant/WeIdConstant.java b/src/main/java/com/webank/weid/constant/WeIdConstant.java index e74fbf4f..09c93524 100644 --- a/src/main/java/com/webank/weid/constant/WeIdConstant.java +++ b/src/main/java/com/webank/weid/constant/WeIdConstant.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.constant; @@ -32,7 +15,7 @@ public final class WeIdConstant { * The Constant WeIdentity DID Document Protocol Version. */ public static final String WEID_DOC_PROTOCOL_VERSION = - "\"@context\": \"https://weidentity.webank.com/did/v1\","; + "\"@context\" : \"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1\","; /** * The Constant GAS_PRICE. @@ -77,12 +60,27 @@ public final class WeIdConstant { /** * The Constant WeIdentity DID Long Array Length. */ - public static final Integer LONG_ARRAY_LENGTH = 8; + public static final Integer CPT_LONG_ARRAY_LENGTH = 8; /** * The Constant WeIdentity DID String Array Length. */ - public static final Integer STRING_ARRAY_LENGTH = 8; + public static final Integer CPT_STRING_ARRAY_LENGTH = 8; + + /** + * The Constant Authority Issuer contract array length. + */ + public static final Integer AUTHORITY_ISSUER_ARRAY_LEGNTH = 16; + + /** + * The Constant Authority Issuer extra param list max length. + */ + public static final Integer AUTHORITY_ISSUER_EXTRA_PARAM_LENGTH = 10; + + /** + * The default accumulator value. + */ + public static final String DEFAULT_ACCUMULATOR_VALUE = "1"; /** * The Constant WeIdentity DID Json Schema Array Length. @@ -115,9 +113,9 @@ public final class WeIdConstant { public static final String PIPELINE = "|"; /** - * The Constant default Certificate Context. + * The Constant separator character. */ - public static final String DEFAULT_CERTIFICATE_CONTEXT = "v1"; + public static final String SEPARATOR = "|"; /** * The Constant Max authority issuer name length in Chars. @@ -133,4 +131,167 @@ public final class WeIdConstant { * The Constant REMOVE_AUTHORITY_ISSUER_OPCODE from contract layer. */ public static final Integer REMOVE_AUTHORITY_ISSUER_OPCODE = 1; + + /** + * 0L. + */ + public static final Long LONG_VALUE_ZERO = 0L; + + /** + * Hex Prefix. + */ + public static final String HEX_PREFIX = "0x"; + + /** + * UUID Separator. + */ + public static final String UUID_SEPARATOR = "-"; + + /** + * WeId Separator. + */ + public static final String WEID_SEPARATOR = ":"; + + /** + * UUID Pattern. + */ + public static final String UUID_PATTERN = + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"; + + /** + * The transaction poll interval. + */ + public static final Integer POLL_TRANSACTION_SLEEP_DURATION = 1500; + + /** + * The transaction poll attempts (max). + */ + public static final Integer POLL_TRANSACTION_ATTEMPTS = 5; + + /** + * transaction poll total time + */ + public static final Integer POLL_TRANSACTION_TOTAL_DURATION = POLL_TRANSACTION_SLEEP_DURATION * POLL_TRANSACTION_ATTEMPTS; + + /** + * The additive block height. + */ + public static final Integer ADDITIVE_BLOCK_HEIGHT = 500; + + /** + * The big-enough block limit number. + */ + public static final String BIG_BLOCK_LIMIT = "9999999999"; + + /** + * The Constant default Presentation type. + */ + public static final String DEFAULT_PRESENTATION_TYPE = "VerifiablePresentation"; + + /** + * The default maximum authority issuer list size to fetch from blockchain. + */ + public static final Integer MAX_AUTHORITY_ISSUER_LIST_SIZE = 50; + + /** + * The Constant WeIdentity DID Event Attribute Change String Name. + */ + public static final String WEID_EVENT_ATTRIBUTE_CHANGE = "WeIdAttributeChanged"; + + /** + * The FISCO-BCOS Address pattern. + */ + public static final String FISCO_BCOS_ADDRESS_PATTERN = "0x[a-fA-f0-9]{40}"; + + /** + * The hash value pattern. + */ + public static final String HASH_VALUE_PATTERN = "0x[a-fA-f0-9]{64}"; + + /** + * The FISCO-BCOS Address pattern. + */ + public static final String FISCO_BCOS_1_X_VERSION_PREFIX = "1"; + public static final String FISCO_BCOS_2_X_VERSION_PREFIX = "2"; + public static final String FISCO_BCOS_3_X_VERSION_PREFIX = "3"; + + /** + * Removed WeID public key specified tag. + */ + public static final String REMOVED_PUBKEY_TAG = "OBSOLETE"; + + /** + * Removed WeID authentication specified tag. + */ + public static final String REMOVED_AUTHENTICATION_TAG = "OBSOLETEAUTH"; + + /** + * Evidence Revoke attribute key. + */ + public static final String EVIDENCE_REVOKE_KEY = "revoke"; + + /** + * Evidence Un-Revoke attribute key. + */ + public static final String EVIDENCE_UNREVOKE_KEY = "unrevoke"; + + /** + * the address key in bucket. + */ + public static final String CNS_WEID_ADDRESS = "WeIdContract"; + public static final String CNS_AUTH_ADDRESS = "AuthorityIssuerController"; + public static final String CNS_SPECIFIC_ADDRESS = "SpecificIssuerController"; + public static final String CNS_EVIDENCE_ADDRESS = "EvidenceFactory"; + public static final String CNS_CPT_ADDRESS = "CptController"; + public static final String CNS_GROUP_ID = "groupId"; + public static final String CNS_CHAIN_ID = "chainId"; + public static final String CNS_GLOBAL_KEY = "globalKey"; + public static final String CNS_MAIN_HASH = "mainHash"; + public static final String CNS_EVIDENCE_HASH = "evidenceHash"; + + /** + * When a block contains ge this much txns, it will be stored in mem cache to save networking. + */ + public static final Integer RECEIPTS_COUNT_THRESHOLD = 100; + + public static final Integer ON_CHAIN_STRING_LENGTH = 2097152; + + public static final Integer ADD_PUBKEY_FAILURE_CODE = -1; + + public static final Integer CPT_DATA_INDEX = 0; + public static final Integer POLICY_DATA_INDEX = 1; + + public static final Long RECOGNIZED_AUTHORITY_ISSUER_FLAG = 1L; + + /* + * State file path for run local + */ + public static final String STATE_FILE_PATH = "output/local_state"; + + public static enum PublicKeyType { + SM2("SM2"), + //RSA("RSA"), + ECDSA("ECDSA"); + + /** + * The Type Name of the Credential Proof. + */ + private String typeName; + + /** + * Constructor. + */ + PublicKeyType(String typeName) { + this.typeName = typeName; + } + + /** + * Getter. + * + * @return typeName + */ + public String getTypeName() { + return typeName; + } + } } diff --git a/src/main/java/com/webank/weid/constant/WeIdEventConstant.java b/src/main/java/com/webank/weid/constant/WeIdEventConstant.java index 4476c719..203a7e92 100644 --- a/src/main/java/com/webank/weid/constant/WeIdEventConstant.java +++ b/src/main/java/com/webank/weid/constant/WeIdEventConstant.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.constant; diff --git a/src/main/java/com/webank/weid/contract/AuthorityIssuerController.java b/src/main/java/com/webank/weid/contract/AuthorityIssuerController.java deleted file mode 100644 index 5dbfc023..00000000 --- a/src/main/java/com/webank/weid/contract/AuthorityIssuerController.java +++ /dev/null @@ -1,458 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.EventEncoder; -import org.bcos.web3j.abi.EventValues; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.Event; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.bcos.web3j.protocol.core.methods.request.EthFilter; -import org.bcos.web3j.protocol.core.methods.response.Log; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; -import rx.Observable; -import rx.functions.Func1; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class AuthorityIssuerController extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getAuthorityIssuerInfoNonAccValue\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"},{\"name\":\"\",\"type\":\"int256[]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"removeAuthorityIssuer\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"attribBytes32\",\"type\":\"bytes32[16]\"},{\"name\":\"attribInt\",\"type\":\"int256[16]\"},{\"name\":\"accValue\",\"type\":\"bytes\"}],\"name\":\"addAuthorityIssuer\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllAuthorityIssuerAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isAuthorityIssuer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"authorityIssuerDataAddress\",\"type\":\"address\"},{\"name\":\"roleControllerAddress\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"operation\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"retCode\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AuthorityIssuerRetLog\",\"type\":\"event\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b6040516040806113cd833981016040528080519060200190919080519060200190919050505b81600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505b611306806100c76000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806313b088ed146100675780634ce9d5ae146101565780635ed43ab21461018c5780637c1ae3701461025f57806392ff8129146102d4575bfe5b341561006f57fe5b61009b600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610322565b6040518080602001806020018381038352858181518152602001915080519060200190602002808383600083146100f1575b8051825260208311156100f1576020820191506020810190506020830392506100cd565b505050905001838103825284818151815260200191508051906020019060200280838360008314610141575b8051825260208311156101415760208201915060208101905060208303925061011d565b50505090500194505050505060405180910390f35b341561015e57fe5b61018a600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061051c565b005b341561019457fe5b61025d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190806102000190601080602002604051908101604052809291908260106020028082843782019150505050509190806102000190601080602002604051908101604052809291908260106020028082843782019150505050509190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506109c6565b005b341561026757fe5b61026f610f69565b60405180806020018281038252838181518152602001915080519060200190602002808383600083146102c1575b8051825260208311156102c15760208201915060208101905060208303925061029d565b5050509050019250505060405180910390f35b34156102dc57fe5b610308600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611164565b604051808215151515815260200191505060405180910390f35b61032a611248565b61033261125c565b61033a611270565b61034261129d565b61034a611248565b61035261125c565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166313b088ed89600060405161040001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505061040060405180830381600087803b151561041857fe5b6102c65a03f1151561042657fe5b50505060405180610200018061020001604052809550819650505060106040518059106104505750595b908082528060200260200182016040525b50925060106040518059106104735750595b908082528060200260200182016040525b509150600090505b601081101561050b5784816010811015156104a357fe5b602002015183828151811015156104b657fe5b90602001906020020190600019169081600019168152505083816010811015156104dc57fe5b602002015182828151811015156104ef57fe5b90602001906020020181815250505b808060010191505061048c565b8282965096505b5050505050915091565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392ff8129826000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15156105de57fe5b6102c65a03f115156105ec57fe5b505050604051805190501515610678577ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa660016207a1ea83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a16109c3565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ae23e1756000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561074557fe5b6102c65a03f1151561075357fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156107e757fe5b6102c65a03f115156107f557fe5b505050604051805190501515610881577ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa660016207a1eb83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a16109c3565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c99ccd77826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b151561093a57fe5b6102c65a03f1151561094857fe5b5050507ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa66001600083604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a15b5b5b50565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392ff8129856000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1515610a8857fe5b6102c65a03f11515610a9657fe5b5050506040518051905015610b21577ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa660006207a1e986604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1610f63565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ae23e1756000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b1515610bee57fe5b6102c65a03f11515610bfc57fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1515610c9057fe5b6102c65a03f11515610c9e57fe5b505050604051805190501515610d2a577ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa660006207a1eb86604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1610f63565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638e1a6209858585856040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184601060200280838360008314610e03575b805182526020831115610e0357602082019150602081019050602083039250610ddf565b50505090500183601060200280838360008314610e3f575b805182526020831115610e3f57602082019150602081019050602083039250610e1b565b50505090500180602001828103825283818151815260200191508051906020019080838360008314610e90575b805182526020831115610e9057602082019150602081019050602083039250610e6c565b505050905090810190601f168015610ebc5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1515610eda57fe5b6102c65a03f11515610ee857fe5b5050507ffcb730e1916430caf8b1752daaa14b59e59354b89170fde494afa6a5f1190fa66000600086604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a15b5b5b50505050565b610f716112c6565b6000610f7b6112c6565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e083a3ad6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561100b57fe5b6102c65a03f1151561101957fe5b505050604051805190509250826040518059106110335750595b908082528060200260200182016040525b509150600090505b8281101561115a57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638667f0e2826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15156110ea57fe5b6102c65a03f115156110f857fe5b50505060405180519050828281518110151561111057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b808060010191505061104c565b8193505b50505090565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392ff8129836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561122857fe5b6102c65a03f1151561123657fe5b5050506040518051905090505b919050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b610200604051908101604052806010905b6000600019168152602001906001900390816112815790505090565b610200604051908101604052806010905b60008152602001906001900390816112ae5790505090565b6020604051908101604052806000815250905600a165627a7a72305820a83d48fffdad25e8997dd8b583401316fe665436937f7b6b716f247a95ce58e00029"; - - private AuthorityIssuerController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private AuthorityIssuerController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private AuthorityIssuerController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private AuthorityIssuerController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Gets the authority issuer ret log events. - * - * @param transactionReceipt the transaction receipt - * @return the authority issuer ret log events - */ - public static List getAuthorityIssuerRetLogEvents( - TransactionReceipt transactionReceipt) { - final Event event = - new Event( - "AuthorityIssuerRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference

() { - })); - List valueList = extractEventParameters(event, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValues eventValues : valueList) { - AuthorityIssuerRetLogEventResponse typedResponse = new AuthorityIssuerRetLogEventResponse(); - typedResponse.operation = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.addr = (Address) eventValues.getNonIndexedValues().get(2); - responses.add(typedResponse); - } - return responses; - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param authorityIssuerDataAddress the authority issuer data address - * @param roleControllerAddress the role controller address - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address authorityIssuerDataAddress, - Address roleControllerAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor( - Arrays.asList(authorityIssuerDataAddress, roleControllerAddress)); - return deployAsync( - AuthorityIssuerController.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param authorityIssuerDataAddress the authority issuer data address - * @param roleControllerAddress the role controller address - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address authorityIssuerDataAddress, - Address roleControllerAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor( - Arrays.asList(authorityIssuerDataAddress, roleControllerAddress)); - return deployAsync( - AuthorityIssuerController.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web 3 j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer controller - */ - public static AuthorityIssuerController load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerController( - contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer controller - */ - public static AuthorityIssuerController load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerController( - contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer controller - */ - public static AuthorityIssuerController loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerController( - contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer controller - */ - public static AuthorityIssuerController loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerController( - contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - /** - * Authority issuer ret log event observable. - * - * @param startBlock the start block - * @param endBlock the end block - * @return the observable - */ - public Observable authorityIssuerRetLogEventObservable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - final Event event = - new Event( - "AuthorityIssuerRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference
() { - })); - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(event)); - return web3j - .ethLogObservable(filter) - .map( - new Func1() { - @Override - public AuthorityIssuerRetLogEventResponse call(Log log) { - EventValues eventValues = extractEventParameters(event, log); - AuthorityIssuerRetLogEventResponse typedResponse = - new AuthorityIssuerRetLogEventResponse(); - typedResponse.operation = (Uint256) eventValues.getNonIndexedValues() - .get(0); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.addr = (Address) eventValues.getNonIndexedValues().get(2); - return typedResponse; - } - }); - } - - /** - * Gets the authority issuer info non acc value. - * - * @param addr the addr - * @return the authority issuer info non acc value - */ - public Future> getAuthorityIssuerInfoNonAccValue(Address addr) { - Function function = - new Function( - "getAuthorityIssuerInfoNonAccValue", - Arrays.asList(addr), - Arrays.>asList( - new TypeReference>() { - }, - new TypeReference>() { - })); - return executeCallMultipleValueReturnAsync(function); - } - - /** - * Removes the authority issuer. - * - * @param addr the addr - * @return the future - */ - public Future removeAuthorityIssuer(Address addr) { - Function function = - new Function( - "removeAuthorityIssuer", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Removes the authority issuer. - * - * @param addr the addr - * @param callback the callback - */ - public void removeAuthorityIssuer(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "removeAuthorityIssuer", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Adds the authority issuer. - * - * @param addr the addr - * @param attribBytes32 the attrib bytes 32 - * @param attribInt the attrib int - * @param accValue the acc value - * @return the future - */ - public Future addAuthorityIssuer( - Address addr, - StaticArray attribBytes32, - StaticArray attribInt, - DynamicBytes accValue) { - Function function = - new Function( - "addAuthorityIssuer", - Arrays.asList(addr, attribBytes32, attribInt, accValue), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Adds the authority issuer. - * - * @param addr the addr - * @param attribBytes32 the attrib bytes 32 - * @param attribInt the attrib int - * @param accValue the acc value - * @param callback the callback - */ - public void addAuthorityIssuer( - Address addr, - StaticArray attribBytes32, - StaticArray attribInt, - DynamicBytes accValue, - TransactionSucCallback callback) { - Function function = - new Function( - "addAuthorityIssuer", - Arrays.asList(addr, attribBytes32, attribInt, accValue), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Gets the all authority issuer address. - * - * @return the all authority issuer address - */ - public Future> getAllAuthorityIssuerAddress() { - Function function = - new Function( - "getAllAuthorityIssuerAddress", - Arrays.asList(), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Checks if is authority issuer. - * - * @param addr the addr - * @return the future - */ - public Future isAuthorityIssuer(Address addr) { - Function function = - new Function( - "isAuthorityIssuer", - Arrays.asList(addr), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * The Class AuthorityIssuerRetLogEventResponse. - */ - public static class AuthorityIssuerRetLogEventResponse { - - /** - * The operation. - */ - public Uint256 operation; - - /** - * The ret code. - */ - public Uint256 retCode; - - /** - * The addr. - */ - public Address addr; - } -} diff --git a/src/main/java/com/webank/weid/contract/AuthorityIssuerData.java b/src/main/java/com/webank/weid/contract/AuthorityIssuerData.java deleted file mode 100644 index 2692dbc4..00000000 --- a/src/main/java/com/webank/weid/contract/AuthorityIssuerData.java +++ /dev/null @@ -1,378 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class AuthorityIssuerData extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getAuthorityIssuerInfoNonAccValue\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[16]\"},{\"name\":\"\",\"type\":\"int256[16]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAuthorityIssuerFromIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"attribBytes32\",\"type\":\"bytes32[16]\"},{\"name\":\"attribInt\",\"type\":\"int256[16]\"},{\"name\":\"accValue\",\"type\":\"bytes\"}],\"name\":\"addAuthorityIssuerFromAddress\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isAuthorityIssuer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getAuthorityIssuerInfoAccValue\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"deleteAuthorityIssuerFromAddress\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getDatasetLength\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b604051602080611446833981016040528080519060200190919050505b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505b6113ca8061007c6000396000f30060606040523615610081576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806313b088ed146100835780638667f0e2146101405780638e1a6209146101a057806392ff812914610273578063b4000950146102c1578063c99ccd771461037e578063e083a3ad146103b4575bfe5b341561008b57fe5b6100b7600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103da565b60405180836010602002808383600083146100f1575b8051825260208311156100f1576020820191506020810190506020830392506100cd565b5050509050018260106020028083836000831461012d575b80518252602083111561012d57602082019150602081019050602083039250610109565b5050509050019250505060405180910390f35b341561014857fe5b61015e6004808035906020019091905050610509565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101a857fe5b610271600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190806102000190601080602002604051908101604052809291908260106020028082843782019150505050509190806102000190601080602002604051908101604052809291908260106020028082843782019150505050509190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190505061054f565b005b341561027b57fe5b6102a7600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061098d565b604051808215151515815260200191505060405180910390f35b34156102c957fe5b6102f5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a34565b6040518080602001828103825283818151815260200191508051906020019080838360008314610344575b80518252602083111561034457602082019150602081019050602083039250610320565b505050905090810190601f1680156103705780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561038657fe5b6103b2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b1f565b005b34156103bc57fe5b6103c461104c565b6040518082815260200191505060405180910390f35b6103e261105a565b6103ea611087565b6103f261105a565b6103fa611087565b6000600090505b60108110156104fa57600060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018160108110151561045957fe5b0160005b5054838260108110151561046d57fe5b60200201906000191690816000191681525050600060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020601001816010811015156104cf57fe5b0160005b505482826010811015156104e357fe5b6020020181815250505b8080600101915050610401565b8282945094505b505050915091565b600060018281548110151561051a57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b6105576110b0565b6105608561098d565b1561056a57610986565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ae23e1756000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561063757fe5b6102c65a03f1151561064557fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156106d957fe5b6102c65a03f115156106e757fe5b5050506040518051905015156106fc57610986565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637fde1c8a86600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f017b58c6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b15156107c957fe5b6102c65a03f115156107d757fe5b505050604051805190506040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b151561086257fe5b6102c65a03f1151561087057fe5b50505060606040519081016040528085815260200184815260200183815250905080600060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000820151816000019060106108e89291906110e5565b5060208201518160100190601061090092919061112b565b50604082015181602001908051906020019061091d92919061116b565b509050506001805480600101828161093591906111eb565b916000526020600020900160005b87909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b5050505050565b60006000600090505b600180549050811015610a29578273ffffffffffffffffffffffffffffffffffffffff166001828154811015156109c957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a1b5760019150610a2e565b5b8080600101915050610996565b600091505b50919050565b610a3c611217565b600060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206020018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b125780601f10610ae757610100808354040283529160200191610b12565b820191906000526020600020905b815481529060010190602001808311610af557829003601f168201915b505050505090505b919050565b60006000610b2c8361098d565b1515610b3757611047565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ae23e1756000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b1515610c0457fe5b6102c65a03f11515610c1257fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1515610ca657fe5b6102c65a03f11515610cb457fe5b505050604051805190501515610cc957611047565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379db5f6784600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f017b58c6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b1515610d9657fe5b6102c65a03f11515610da457fe5b505050604051805190506040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b1515610e2f57fe5b6102c65a03f11515610e3d57fe5b505050600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600082016000610e91919061122b565b601082016000610ea1919061123e565b602082016000610eb19190611251565b50506001805490509150600090505b81811015610f4a578273ffffffffffffffffffffffffffffffffffffffff16600182815481101515610eee57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610f3c57610f4a565b5b8080600101915050610ec0565b6001820381141515610fef57600160018303815481101515610f6857fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600182815481101515610fa457fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60016001830381548110151561100157fe5b906000526020600020900160005b6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018054809190600190036110459190611299565b505b505050565b600060018054905090505b90565b610200604051908101604052806010905b60006000191681526020019060019003908161106b5790505090565b610200604051908101604052806010905b60008152602001906001900390816110985790505090565b610420604051908101604052806110c56112c5565b81526020016110d26112f2565b81526020016110df61131b565b81525090565b826010810192821561111a579160200282015b828111156111195782518290600019169055916020019190600101906110f8565b5b509050611127919061132f565b5090565b826010810192821561115a579160200282015b8281111561115957825182559160200191906001019061113e565b5b5090506111679190611354565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106111ac57805160ff19168380011785556111da565b828001600101855582156111da579182015b828111156111d95782518255916020019190600101906111be565b5b5090506111e79190611379565b5090565b815481835581811511611212578183600052602060002091820191016112119190611379565b5b505050565b602060405190810160405280600081525090565b50806010019061123b919061132f565b50565b50806010019061124e9190611354565b50565b50805460018160011615610100020316600290046000825580601f106112775750611296565b601f0160209004906000526020600020908101906112959190611379565b5b50565b8154818355818115116112c0578183600052602060002091820191016112bf9190611379565b5b505050565b610200604051908101604052806010905b6000600019168152602001906001900390816112d65790505090565b610200604051908101604052806010905b60008152602001906001900390816113035790505090565b602060405190810160405280600081525090565b61135191905b8082111561134d576000816000905550600101611335565b5090565b90565b61137691905b8082111561137257600081600090555060010161135a565b5090565b90565b61139b91905b8082111561139757600081600090555060010161137f565b5090565b905600a165627a7a72305820ee9c55852cfd4cfce443b2d8924617df969dffe8c7af316269554d0e4f41b77e0029"; - - private AuthorityIssuerData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private AuthorityIssuerData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private AuthorityIssuerData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private AuthorityIssuerData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param addr the addr - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address addr) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(addr)); - return deployAsync( - AuthorityIssuerData.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param addr the addr - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address addr) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(addr)); - return deployAsync( - AuthorityIssuerData.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer data - */ - public static AuthorityIssuerData load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerData(contractAddress, web3j, credentials, gasPrice, gasLimit, - false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer data - */ - public static AuthorityIssuerData load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerData( - contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer data - */ - public static AuthorityIssuerData loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerData(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the authority issuer data - */ - public static AuthorityIssuerData loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new AuthorityIssuerData( - contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - /** - * Gets the authority issuer info non acc value. - * - * @param addr the addr - * @return the authority issuer info non acc value - */ - public Future> getAuthorityIssuerInfoNonAccValue(Address addr) { - Function function = - new Function( - "getAuthorityIssuerInfoNonAccValue", - Arrays.asList(addr), - Arrays.>asList( - new TypeReference>() { - }, - new TypeReference>() { - })); - return executeCallMultipleValueReturnAsync(function); - } - - /** - * Gets the authority issuer from index. - * - * @param index the index - * @return the authority issuer from index - */ - public Future

getAuthorityIssuerFromIndex(Uint256 index) { - Function function = - new Function( - "getAuthorityIssuerFromIndex", - Arrays.asList(index), - Arrays.>asList(new TypeReference
() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Adds the authority issuer from address. - * - * @param addr the addr - * @param attribBytes32 the attrib bytes 32 - * @param attribInt the attrib int - * @param accValue the acc value - * @return the future - */ - public Future addAuthorityIssuerFromAddress( - Address addr, - StaticArray attribBytes32, - StaticArray attribInt, - DynamicBytes accValue) { - Function function = - new Function( - "addAuthorityIssuerFromAddress", - Arrays.asList(addr, attribBytes32, attribInt, accValue), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Adds the authority issuer from address. - * - * @param addr the addr - * @param attribBytes32 the attrib bytes 32 - * @param attribInt the attrib int - * @param accValue the acc value - * @param callback the callback - */ - public void addAuthorityIssuerFromAddress( - Address addr, - StaticArray attribBytes32, - StaticArray attribInt, - DynamicBytes accValue, - TransactionSucCallback callback) { - Function function = - new Function( - "addAuthorityIssuerFromAddress", - Arrays.asList(addr, attribBytes32, attribInt, accValue), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Checks if is authority issuer. - * - * @param addr the addr - * @return the future - */ - public Future isAuthorityIssuer(Address addr) { - Function function = - new Function( - "isAuthorityIssuer", - Arrays.asList(addr), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Gets the authority issuer info acc value. - * - * @param addr the addr - * @return the authority issuer info acc value - */ - public Future getAuthorityIssuerInfoAccValue(Address addr) { - Function function = - new Function( - "getAuthorityIssuerInfoAccValue", - Arrays.asList(addr), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Delete authority issuer from address. - * - * @param addr the addr - * @return the future - */ - public Future deleteAuthorityIssuerFromAddress(Address addr) { - Function function = - new Function( - "deleteAuthorityIssuerFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Delete authority issuer from address. - * - * @param addr the addr - * @param callback the callback - */ - public void deleteAuthorityIssuerFromAddress(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "deleteAuthorityIssuerFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Gets the dataset length. - * - * @return the dataset length - */ - public Future getDatasetLength() { - Function function = - new Function( - "getDatasetLength", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } -} diff --git a/src/main/java/com/webank/weid/contract/CommitteeMemberController.java b/src/main/java/com/webank/weid/contract/CommitteeMemberController.java deleted file mode 100644 index b0d5286a..00000000 --- a/src/main/java/com/webank/weid/contract/CommitteeMemberController.java +++ /dev/null @@ -1,419 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.EventEncoder; -import org.bcos.web3j.abi.EventValues; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.Event; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.bcos.web3j.protocol.core.methods.request.EthFilter; -import org.bcos.web3j.protocol.core.methods.response.Log; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; -import rx.Observable; -import rx.functions.Func1; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class CommitteeMemberController extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":true,\"inputs\":[],\"name\":\"getAllCommitteeMemberAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"removeCommitteeMember\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isCommitteeMember\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"addCommitteeMember\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"committeeMemberDataAddress\",\"type\":\"address\"},{\"name\":\"roleControllerAddress\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"operation\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"retCode\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"CommitteeRetLog\",\"type\":\"event\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b604051604080610ec4833981016040528080519060200190919080519060200190919050505b81600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505b610dfd806100c76000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c0d9c1e1461005c5780637fad0d48146100d1578063e636d84b14610107578063e7f1f95314610155575bfe5b341561006457fe5b61006c61018b565b60405180806020018281038252838181518152602001915080519060200190602002808383600083146100be575b8051825260208311156100be5760208201915060208101905060208303925061009a565b5050509050019250505060405180910390f35b34156100d957fe5b610105600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610386565b005b341561010f57fe5b61013b600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610830565b604051808215151515815260200191505060405180910390f35b341561015d57fe5b610189600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610914565b005b610193610dbd565b600061019d610dbd565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e083a3ad6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561022d57fe5b6102c65a03f1151561023b57fe5b505050604051805190509250826040518059106102555750595b908082528060200260200182016040525b509150600090505b8281101561037c57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396d5afbf826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b151561030c57fe5b6102c65a03f1151561031a57fe5b50505060405180519050828281518110151561033257fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b808060010191505061026e565b8193505b50505090565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e636d84b826000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561044857fe5b6102c65a03f1151561045657fe5b5050506040518051905015156104e2577f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a660016207a21c83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a161082d565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c6d8a3f36000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b15156105af57fe5b6102c65a03f115156105bd57fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561065157fe5b6102c65a03f1151561065f57fe5b5050506040518051905015156106eb577f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a660016207a21d83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a161082d565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166378f341ef826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b15156107a457fe5b6102c65a03f115156107b257fe5b5050507f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a66001600083604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a15b5b5b50565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e636d84b836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15156108f457fe5b6102c65a03f1151561090257fe5b5050506040518051905090505b919050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e636d84b826000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15156109d657fe5b6102c65a03f115156109e457fe5b5050506040518051905015610a6f577f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a660006207a21b83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1610dba565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c6d8a3f36000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b1515610b3c57fe5b6102c65a03f11515610b4a57fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1515610bde57fe5b6102c65a03f11515610bec57fe5b505050604051805190501515610c78577f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a660006207a21d83604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1610dba565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d9d2619c826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1515610d3157fe5b6102c65a03f11515610d3f57fe5b5050507f3bd22f9efc9b65160af79bb416016337d6b57061a60af4d5d6c98b0e5936f9a66000600083604051808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a15b5b5b50565b6020604051908101604052806000815250905600a165627a7a72305820d5d91eb9c6e562c45e891a4ebd6864f4c7606499518234d73a7b91fb180cf8210029"; - - private CommitteeMemberController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private CommitteeMemberController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private CommitteeMemberController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private CommitteeMemberController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Gets the committee ret log events. - * - * @param transactionReceipt the transaction receipt - * @return the committee ret log events - */ - public static List getCommitteeRetLogEvents( - TransactionReceipt transactionReceipt) { - final Event event = - new Event( - "CommitteeRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference

() { - })); - List valueList = extractEventParameters(event, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValues eventValues : valueList) { - CommitteeRetLogEventResponse typedResponse = new CommitteeRetLogEventResponse(); - typedResponse.operation = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.addr = (Address) eventValues.getNonIndexedValues().get(2); - responses.add(typedResponse); - } - return responses; - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param committeeMemberDataAddress the committee member data address - * @param roleControllerAddress the role controller address - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address committeeMemberDataAddress, - Address roleControllerAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor( - Arrays.asList(committeeMemberDataAddress, roleControllerAddress)); - return deployAsync( - CommitteeMemberController.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param committeeMemberDataAddress the committee member data address - * @param roleControllerAddress the role controller address - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address committeeMemberDataAddress, - Address roleControllerAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor( - Arrays.asList(committeeMemberDataAddress, roleControllerAddress)); - return deployAsync( - CommitteeMemberController.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member controller - */ - public static CommitteeMemberController load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberController( - contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member controller - */ - public static CommitteeMemberController load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberController( - contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member controller - */ - public static CommitteeMemberController loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberController( - contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member controller - */ - public static CommitteeMemberController loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberController( - contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - /** - * Committee ret log event observable. - * - * @param startBlock the start block - * @param endBlock the end block - * @return the observable - */ - public Observable committeeRetLogEventObservable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - final Event event = - new Event( - "CommitteeRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference
() { - })); - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(event)); - return web3j - .ethLogObservable(filter) - .map( - new Func1() { - @Override - public CommitteeRetLogEventResponse call(Log log) { - EventValues eventValues = extractEventParameters(event, log); - CommitteeRetLogEventResponse typedResponse = new CommitteeRetLogEventResponse(); - typedResponse.operation = (Uint256) eventValues.getNonIndexedValues() - .get(0); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.addr = (Address) eventValues.getNonIndexedValues().get(2); - return typedResponse; - } - }); - } - - /** - * Gets the all committee member address. - * - * @return the all committee member address - */ - public Future> getAllCommitteeMemberAddress() { - Function function = - new Function( - "getAllCommitteeMemberAddress", - Arrays.asList(), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Removes the committee member. - * - * @param addr the addr - * @return the future - */ - public Future removeCommitteeMember(Address addr) { - Function function = - new Function( - "removeCommitteeMember", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Removes the committee member. - * - * @param addr the addr - * @param callback the callback - */ - public void removeCommitteeMember(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "removeCommitteeMember", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Checks if is committee member. - * - * @param addr the addr - * @return the future - */ - public Future isCommitteeMember(Address addr) { - Function function = - new Function( - "isCommitteeMember", - Arrays.asList(addr), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Adds the committee member. - * - * @param addr the addr - * @return the future - */ - public Future addCommitteeMember(Address addr) { - Function function = - new Function( - "addCommitteeMember", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Adds the committee member. - * - * @param addr the addr - * @param callback the callback - */ - public void addCommitteeMember(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "addCommitteeMember", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * The Class CommitteeRetLogEventResponse. - */ - public static class CommitteeRetLogEventResponse { - - /** - * The operation. - */ - public Uint256 operation; - - /** - * The ret code. - */ - public Uint256 retCode; - - /** - * The addr. - */ - public Address addr; - } -} diff --git a/src/main/java/com/webank/weid/contract/CommitteeMemberData.java b/src/main/java/com/webank/weid/contract/CommitteeMemberData.java deleted file mode 100644 index faabf978..00000000 --- a/src/main/java/com/webank/weid/contract/CommitteeMemberData.java +++ /dev/null @@ -1,323 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class CommitteeMemberData extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"deleteCommitteeMemberFromAddress\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getCommitteeMemberAddressFromIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"addCommitteeMemberFromAddress\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getDatasetLength\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isCommitteeMember\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b604051602080610c05833981016040528080519060200190919050505b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505b610b898061007c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806378f341ef1461006757806396d5afbf1461009d578063d9d2619c146100fd578063e083a3ad14610133578063e636d84b14610159575bfe5b341561006f57fe5b61009b600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a7565b005b34156100a557fe5b6100bb6004808035906020019091905050610661565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561010557fe5b610131600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106a7565b005b341561013b57fe5b610143610a2b565b6040518082815260200191505060405180910390f35b341561016157fe5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a39565b604051808215151515815260200191505060405180910390f35b600060006101b483610a39565b15156101bf5761065c565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c6d8a3f36000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561028c57fe5b6102c65a03f1151561029a57fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561032e57fe5b6102c65a03f1151561033c57fe5b5050506040518051905015156103515761065c565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379db5f6784600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663793387466000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561041e57fe5b6102c65a03f1151561042c57fe5b505050604051805190506040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15156104b757fe5b6102c65a03f115156104c557fe5b5050506000805490509150600090505b8181101561055f578273ffffffffffffffffffffffffffffffffffffffff1660008281548110151561050357fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156105515761055f565b5b80806001019150506104d5565b60018203811415156106045760006001830381548110151561057d57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000828154811015156105b957fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60006001830381548110151561061657fe5b906000526020600020900160005b6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600080548091906001900361065a9190610ae0565b505b505050565b600060008281548110151561067257fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b6106b081610a39565b156106ba57610a28565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a63f6532600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c6d8a3f36000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561078757fe5b6102c65a03f1151561079557fe5b505050604051805190506000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561082957fe5b6102c65a03f1151561083757fe5b50505060405180519050151561084c57610a28565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637fde1c8a82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663793387466000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050602060405180830381600087803b151561091957fe5b6102c65a03f1151561092757fe5b505050604051805190506040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15156109b257fe5b6102c65a03f115156109c057fe5b505050600080548060010182816109d79190610b0c565b916000526020600020900160005b83909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b50565b600060008054905090505b90565b60006000600090505b600080549050811015610ad5578273ffffffffffffffffffffffffffffffffffffffff16600082815481101515610a7557fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610ac75760019150610ada565b5b8080600101915050610a42565b600091505b50919050565b815481835581811511610b0757818360005260206000209182019101610b069190610b38565b5b505050565b815481835581811511610b3357818360005260206000209182019101610b329190610b38565b5b505050565b610b5a91905b80821115610b56576000816000905550600101610b3e565b5090565b905600a165627a7a723058206e28f60e0dd7d3ff84bb268f7eaf713c2b9e70bd1864ae4f4fc08b915738d4f50029"; - - private CommitteeMemberData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private CommitteeMemberData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private CommitteeMemberData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private CommitteeMemberData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param addr the addr - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address addr) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(addr)); - return deployAsync( - CommitteeMemberData.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @param addr the addr - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address addr) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(addr)); - return deployAsync( - CommitteeMemberData.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member data - */ - public static CommitteeMemberData load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberData(contractAddress, web3j, credentials, gasPrice, gasLimit, - false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member data - */ - public static CommitteeMemberData load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberData( - contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member data - */ - public static CommitteeMemberData loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberData(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the committee member data - */ - public static CommitteeMemberData loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CommitteeMemberData( - contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - /** - * Delete committee member from address. - * - * @param addr the addr - * @return the future - */ - public Future deleteCommitteeMemberFromAddress(Address addr) { - Function function = - new Function( - "deleteCommitteeMemberFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Delete committee member from address. - * - * @param addr the addr - * @param callback the callback - */ - public void deleteCommitteeMemberFromAddress(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "deleteCommitteeMemberFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Gets the committee member address from index. - * - * @param index the index - * @return the committee member address from index - */ - public Future

getCommitteeMemberAddressFromIndex(Uint256 index) { - Function function = - new Function( - "getCommitteeMemberAddressFromIndex", - Arrays.asList(index), - Arrays.>asList(new TypeReference
() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Adds the committee member from address. - * - * @param addr the addr - * @return the future - */ - public Future addCommitteeMemberFromAddress(Address addr) { - Function function = - new Function( - "addCommitteeMemberFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Adds the committee member from address. - * - * @param addr the addr - * @param callback the callback - */ - public void addCommitteeMemberFromAddress(Address addr, TransactionSucCallback callback) { - Function function = - new Function( - "addCommitteeMemberFromAddress", - Arrays.asList(addr), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Gets the dataset length. - * - * @return the dataset length - */ - public Future getDatasetLength() { - Function function = - new Function( - "getDatasetLength", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Checks if is committee member. - * - * @param addr the addr - * @return the future - */ - public Future isCommitteeMember(Address addr) { - Function function = - new Function( - "isCommitteeMember", - Arrays.asList(addr), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } -} diff --git a/src/main/java/com/webank/weid/contract/CptController.java b/src/main/java/com/webank/weid/contract/CptController.java deleted file mode 100644 index cb737a2c..00000000 --- a/src/main/java/com/webank/weid/contract/CptController.java +++ /dev/null @@ -1,425 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.EventEncoder; -import org.bcos.web3j.abi.EventValues; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.Event; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.bcos.web3j.protocol.core.methods.request.EthFilter; -import org.bcos.web3j.protocol.core.methods.response.Log; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; -import rx.Observable; -import rx.functions.Func1; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class CptController extends Contract { - - public static final String ABI = - "[{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptDynamicBytes32Array\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"},{\"name\":\"publisher\",\"type\":\"address\"},{\"name\":\"intArray\",\"type\":\"int256[8]\"},{\"name\":\"bytes32Array\",\"type\":\"bytes32[8]\"},{\"name\":\"jsonSchemaArray\",\"type\":\"bytes32[128]\"},{\"name\":\"v\",\"type\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"updateCpt\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"queryCpt\",\"outputs\":[{\"name\":\"publisher\",\"type\":\"address\"},{\"name\":\"intArray\",\"type\":\"int256[]\"},{\"name\":\"bytes32Array\",\"type\":\"bytes32[]\"},{\"name\":\"jsonSchemaArray\",\"type\":\"bytes32[]\"},{\"name\":\"v\",\"type\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptDynamicIntArray\",\"outputs\":[{\"name\":\"\",\"type\":\"int256[]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"publisher\",\"type\":\"address\"},{\"name\":\"intArray\",\"type\":\"int256[8]\"},{\"name\":\"bytes32Array\",\"type\":\"bytes32[8]\"},{\"name\":\"jsonSchemaArray\",\"type\":\"bytes32[128]\"},{\"name\":\"v\",\"type\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"registerCpt\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptDynamicJsonSchemaArray\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"cptDataAddress\",\"type\":\"address\"},{\"name\":\"weIdContractAddress\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"retCode\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cptId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cptVersion\",\"type\":\"int256\"}],\"name\":\"RegisterCptRetLog\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"retCode\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cptId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cptVersion\",\"type\":\"int256\"}],\"name\":\"UpdateCptRetLog\",\"type\":\"event\"}]"; - private static String BINARY = - "6060604052341561000c57fe5b604051604080611724833981016040528080519060200190919080519060200190919050505b81600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505b61165d806100c76000396000f30060606040523615610076576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063102b508d1461007857806351c10fee146100fb5780635ca35abf146101ff578063672ddcf01461038c578063a8550a521461040f578063b4af70901461050a575bfe5b341561008057fe5b610096600480803590602001909190505061058d565b60405180806020018281038252838181518152602001915080519060200190602002808383600083146100e8575b8051825260208311156100e8576020820191506020810190506020830392506100c4565b5050509050019250505060405180910390f35b341561010357fe5b6101e5600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806110000190608080602002604051908101604052809291908260806020028082843782019150505050509190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506106e0565b604051808215151515815260200191505060405180910390f35b341561020757fe5b61021d6004808035906020019091905050610c6e565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200180602001806020018760ff1660ff1681526020018660001916600019168152602001856000191660001916815260200184810384528a8181518152602001915080519060200190602002808383600083146102d1575b8051825260208311156102d1576020820191506020810190506020830392506102ad565b505050905001848103835289818151815260200191508051906020019060200280838360008314610321575b805182526020831115610321576020820191506020810190506020830392506102fd565b505050905001848103825288818151815260200191508051906020019060200280838360008314610371575b8051825260208311156103715760208201915060208101905060208303925061034d565b5050509050019a505050505050505050505060405180910390f35b341561039457fe5b6103aa6004808035906020019091905050610e31565b60405180806020018281038252838181518152602001915080519060200190602002808383600083146103fc575b8051825260208311156103fc576020820191506020810190506020830392506103d8565b5050509050019250505060405180910390f35b341561041757fe5b6104f0600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806110000190608080602002604051908101604052809291908260806020028082843782019150505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610f7b565b604051808215151515815260200191505060405180910390f35b341561051257fe5b6105286004808035906020019091905050611432565b604051808060200182810382528381815181526020019150805190602001906020028083836000831461057a575b80518252602083111561057a57602082019150602081019050602083039250610556565b5050509050019250505060405180910390f35b610595611586565b61059d61159a565b6105a5611586565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166227baa486600060405161010001526040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505061010060405180830381600087803b151561063e57fe5b6102c65a03f1151561064c57fe5b50505060405180610100016040529250600860405180591061066b5750595b908082528060200260200182016040525b509150600090505b60088110156106d457828160088110151561069b57fe5b602002015182828151811015156106ae57fe5b9060200190602002019060001916908160001916815250505b8080600101915050610684565b8193505b505050919050565b60006106ea6115c7565b60006000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663170abf9c8c6000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15156107b057fe5b6102c65a03f115156107be57fe5b505050604051805190501515610823577f2614d1ec3482cc2505bf211c39bee96c28940521311ec70c9ebf14d3896fd1966207a24f6000600060405180848152602001838152602001828152602001935050505060405180910390a160009350610c5f565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d4eb8a428d6000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15156108b957fe5b6102c65a03f115156108c757fe5b5050506040518051905015610c0957600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b746f18d600060405161010001526040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505061010060405180830381600087803b151561096e57fe5b6102c65a03f1151561097c57fe5b50505060405180610100016040529250600183600060088110151561099d57fe5b6020020151019150818a60006008811015156109b557fe5b6020020181815250508260016008811015156109cd57fe5b60200201519050808a60016008811015156109e457fe5b602002018181525050600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354ed7f4a8d8d8d8d8d8d8d8d6000604051602001526040518963ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808981526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200187600860200280838360008314610ad9575b805182526020831115610ad957602082019150602081019050602083039250610ab5565b50505090500186600860200280838360008314610b15575b805182526020831115610b1557602082019150602081019050602083039250610af1565b50505090500185608060200280838360008314610b51575b805182526020831115610b5157602082019150602081019050602083039250610b2d565b5050509050018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200198505050505050505050602060405180830381600087803b1515610b9f57fe5b6102c65a03f11515610bad57fe5b50505060405180519050507f2614d1ec3482cc2505bf211c39bee96c28940521311ec70c9ebf14d3896fd19660008d8460405180848152602001838152602001828152602001935050505060405180910390a160019350610c5f565b7f2614d1ec3482cc2505bf211c39bee96c28940521311ec70c9ebf14d3896fd1966207a24d6000600060405180848152602001838152602001828152602001935050505060405180910390a160009350610c5f565b5b50505098975050505050505050565b6000610c786115f0565b610c80611586565b610c88611586565b600060006000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636da223b7896000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610d2457fe5b6102c65a03f11515610d3257fe5b505050604051805190509650610d4788610e31565b9550610d528861058d565b9450610d5d88611432565b9350600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e5741ff3896000604051606001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050606060405180830381600087803b1515610df557fe5b6102c65a03f11515610e0357fe5b505050604051805190602001805190602001805190508093508194508295505050505b919395979092949650565b610e396115f0565b610e416115c7565b610e496115f0565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b746f186600060405161010001526040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505061010060405180830381600087803b1515610ee357fe5b6102c65a03f11515610ef157fe5b505050604051806101000160405292506008604051805910610f105750595b908082528060200260200182016040525b509150600090505b6008811015610f6f578281600881101515610f4057fe5b60200201518282815181101515610f5357fe5b90602001906020020181815250505b8080600101915050610f29565b8193505b505050919050565b600060006000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663170abf9c8b6000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561104357fe5b6102c65a03f1151561105157fe5b5050506040518051905015156110b6577fa17f6f29c43d53fdf8a8d5fc788d118621cdca690e8ee29962c3e2fbe70d5eb36207a24f6000600060405180848152602001838152602001828152602001935050505060405180910390a160009250611425565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d19b82868b6000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561117857fe5b6102c65a03f1151561118657fe5b50505060405180519050915060008214156111f0577fa17f6f29c43d53fdf8a8d5fc788d118621cdca690e8ee29962c3e2fbe70d5eb36207a24e6000600060405180848152602001838152602001828152602001935050505060405180910390a160009250611425565b600190508089600060088110151561120457fe5b602002018181525050600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354ed7f4a838c8c8c8c8c8c8c6000604051602001526040518963ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808981526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001876008602002808383600083146112f9575b8051825260208311156112f9576020820191506020810190506020830392506112d5565b50505090500186600860200280838360008314611335575b80518252602083111561133557602082019150602081019050602083039250611311565b50505090500185608060200280838360008314611371575b8051825260208311156113715760208201915060208101905060208303925061134d565b5050509050018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200198505050505050505050602060405180830381600087803b15156113bf57fe5b6102c65a03f115156113cd57fe5b50505060405180519050507fa17f6f29c43d53fdf8a8d5fc788d118621cdca690e8ee29962c3e2fbe70d5eb36000838360405180848152602001838152602001828152602001935050505060405180910390a1600192505b5050979650505050505050565b61143a611586565b611442611604565b61144a611586565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663628e526f86600060405161100001526040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505061100060405180830381600087803b15156114e457fe5b6102c65a03f115156114f257fe5b5050506040518061100001604052925060806040518059106115115750595b908082528060200260200182016040525b509150600090505b608081101561157a57828160808110151561154157fe5b6020020151828281518110151561155457fe5b9060200190602002019060001916908160001916815250505b808060010191505061152a565b8193505b505050919050565b602060405190810160405280600081525090565b610100604051908101604052806008905b6000600019168152602001906001900390816115ab5790505090565b610100604051908101604052806008905b60008152602001906001900390816115d85790505090565b602060405190810160405280600081525090565b611000604051908101604052806080905b60006000191681526020019060019003908161161557905050905600a165627a7a72305820dd501eaa174400033398fdf036941c4cae857a968d83582de1fa61c2d611ca0f0029"; - - private CptController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private CptController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private CptController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private CptController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - public static List getRegisterCptRetLogEvents( - TransactionReceipt transactionReceipt) { - final Event event = - new Event( - "RegisterCptRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - List valueList = extractEventParameters(event, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValues eventValues : valueList) { - RegisterCptRetLogEventResponse typedResponse = new RegisterCptRetLogEventResponse(); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.cptId = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.cptVersion = (Int256) eventValues.getNonIndexedValues().get(2); - responses.add(typedResponse); - } - return responses; - } - - public static List getUpdateCptRetLogEvents( - TransactionReceipt transactionReceipt) { - final Event event = - new Event( - "UpdateCptRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - List valueList = extractEventParameters(event, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValues eventValues : valueList) { - UpdateCptRetLogEventResponse typedResponse = new UpdateCptRetLogEventResponse(); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.cptId = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.cptVersion = (Int256) eventValues.getNonIndexedValues().get(2); - responses.add(typedResponse); - } - return responses; - } - - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address cptDataAddress, - Address weIdContractAddress) { - String encodedConstructor = - FunctionEncoder - .encodeConstructor(Arrays.asList(cptDataAddress, weIdContractAddress)); - return deployAsync( - CptController.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address cptDataAddress, - Address weIdContractAddress) { - String encodedConstructor = - FunctionEncoder - .encodeConstructor(Arrays.asList(cptDataAddress, weIdContractAddress)); - return deployAsync( - CptController.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - public static CptController load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptController(contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - public static CptController load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptController(contractAddress, web3j, transactionManager, gasPrice, gasLimit, - false); - } - - public static CptController loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptController(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - public static CptController loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptController(contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - public Observable registerCptRetLogEventObservable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - final Event event = - new Event( - "RegisterCptRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(event)); - return web3j - .ethLogObservable(filter) - .map( - new Func1() { - @Override - public RegisterCptRetLogEventResponse call(Log log) { - EventValues eventValues = extractEventParameters(event, log); - RegisterCptRetLogEventResponse typedResponse = new RegisterCptRetLogEventResponse(); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.cptId = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.cptVersion = (Int256) eventValues.getNonIndexedValues() - .get(2); - return typedResponse; - } - }); - } - - public Observable updateCptRetLogEventObservable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - final Event event = - new Event( - "UpdateCptRetLog", - Arrays.>asList(), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(event)); - return web3j - .ethLogObservable(filter) - .map( - new Func1() { - @Override - public UpdateCptRetLogEventResponse call(Log log) { - EventValues eventValues = extractEventParameters(event, log); - UpdateCptRetLogEventResponse typedResponse = new UpdateCptRetLogEventResponse(); - typedResponse.retCode = (Uint256) eventValues.getNonIndexedValues().get(0); - typedResponse.cptId = (Uint256) eventValues.getNonIndexedValues().get(1); - typedResponse.cptVersion = (Int256) eventValues.getNonIndexedValues() - .get(2); - return typedResponse; - } - }); - } - - public Future> getCptDynamicBytes32Array(Uint256 cptId) { - Function function = - new Function( - "getCptDynamicBytes32Array", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future updateCpt( - Uint256 cptId, - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) { - Function function = - new Function( - "updateCpt", - Arrays.asList(cptId, publisher, intArray, bytes32Array, jsonSchemaArray, v, r, - s), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - public void updateCpt( - Uint256 cptId, - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s, - TransactionSucCallback callback) { - Function function = - new Function( - "updateCpt", - Arrays.asList(cptId, publisher, intArray, bytes32Array, jsonSchemaArray, v, r, - s), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - public Future> queryCpt(Uint256 cptId) { - Function function = - new Function( - "queryCpt", - Arrays.asList(cptId), - Arrays.>asList( - new TypeReference

() { - }, - new TypeReference>() { - }, - new TypeReference>() { - }, - new TypeReference>() { - }, - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - return executeCallMultipleValueReturnAsync(function); - } - - public Future> getCptDynamicIntArray(Uint256 cptId) { - Function function = - new Function( - "getCptDynamicIntArray", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future registerCpt( - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) { - Function function = - new Function( - "registerCpt", - Arrays.asList(publisher, intArray, bytes32Array, jsonSchemaArray, v, r, s), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - public void registerCpt( - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s, - TransactionSucCallback callback) { - Function function = - new Function( - "registerCpt", - Arrays.asList(publisher, intArray, bytes32Array, jsonSchemaArray, v, r, s), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - public Future> getCptDynamicJsonSchemaArray(Uint256 cptId) { - Function function = - new Function( - "getCptDynamicJsonSchemaArray", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public static class RegisterCptRetLogEventResponse { - - public Uint256 retCode; - - public Uint256 cptId; - - public Int256 cptVersion; - } - - public static class UpdateCptRetLogEventResponse { - - public Uint256 retCode; - - public Uint256 cptId; - - public Int256 cptVersion; - } -} diff --git a/src/main/java/com/webank/weid/contract/CptData.java b/src/main/java/com/webank/weid/contract/CptData.java deleted file mode 100644 index ea026cb9..00000000 --- a/src/main/java/com/webank/weid/contract/CptData.java +++ /dev/null @@ -1,303 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.FunctionEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class CptData extends Contract { - - public static final String ABI = - "[{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptBytes32Array\",\"outputs\":[{\"name\":\"bytes32Array\",\"type\":\"bytes32[8]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptIntArray\",\"outputs\":[{\"name\":\"intArray\",\"type\":\"int256[8]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCpt\",\"outputs\":[{\"name\":\"publisher\",\"type\":\"address\"},{\"name\":\"intArray\",\"type\":\"int256[8]\"},{\"name\":\"bytes32Array\",\"type\":\"bytes32[8]\"},{\"name\":\"jsonSchemaArray\",\"type\":\"bytes32[128]\"},{\"name\":\"v\",\"type\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"},{\"name\":\"cptPublisher\",\"type\":\"address\"},{\"name\":\"cptIntArray\",\"type\":\"int256[8]\"},{\"name\":\"cptBytes32Array\",\"type\":\"bytes32[8]\"},{\"name\":\"cptJsonSchemaArray\",\"type\":\"bytes32[128]\"},{\"name\":\"cptV\",\"type\":\"uint8\"},{\"name\":\"cptR\",\"type\":\"bytes32\"},{\"name\":\"cptS\",\"type\":\"bytes32\"}],\"name\":\"putCpt\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptJsonSchemaArray\",\"outputs\":[{\"name\":\"jsonSchemaArray\",\"type\":\"bytes32[128]\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptPublisher\",\"outputs\":[{\"name\":\"publisher\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"publisher\",\"type\":\"address\"}],\"name\":\"getCptId\",\"outputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"isCptExist\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"cptId\",\"type\":\"uint256\"}],\"name\":\"getCptSignature\",\"outputs\":[{\"name\":\"v\",\"type\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"authorityIssuerDataAddress\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"}]"; - private static String BINARY = - "60606040526064600055621e8480600155341561001857fe5b6040516020806116b5833981016040528080519060200190919050505b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505b61162d806100886000396000f30060606040523615610096576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806227baa41461009857806323b746f11461010257806325e556241461016c57806354ed7f4a146102ae578063628e526f146103b25780636da223b71461041c578063d19b82861461047c578063d4eb8a42146104c6578063e5741ff3146104fe575bfe5b34156100a057fe5b6100b66004808035906020019091905050610556565b60405180826008602002808383600083146100f0575b8051825260208311156100f0576020820191506020810190506020830392506100cc565b50505090500191505060405180910390f35b341561010a57fe5b6101206004808035906020019091905050610718565b604051808260086020028083836000831461015a575b80518252602083111561015a57602082019150602081019050602083039250610136565b50505090500191505060405180910390f35b341561017457fe5b61018a60048080359060200190919050506108da565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001876008602002808383600083146101f6575b8051825260208311156101f6576020820191506020810190506020830392506101d2565b50505090500186600860200280838360008314610232575b8051825260208311156102325760208201915060208101905060208303925061020e565b5050509050018560806020028083836000831461026e575b80518252602083111561026e5760208201915060208101905060208303925061024a565b5050509050018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200197505050505050505060405180910390f35b34156102b657fe5b610398600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509190806110000190608080602002604051908101604052809291908260806020028082843782019150505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610af0565b604051808215151515815260200191505060405180910390f35b34156103ba57fe5b6103d06004808035906020019091905050610c64565b604051808260806020028083836000831461040a575b80518252602083111561040a576020820191506020810190506020830392506103e6565b50505090500191505060405180910390f35b341561042457fe5b61043a6004808035906020019091905050610e26565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561048457fe5b6104b0600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610fe2565b6040518082815260200191505060405180910390f35b34156104ce57fe5b6104e46004808035906020019091905050611105565b604051808215151515815260200191505060405180910390f35b341561050657fe5b61051c6004808035906020019091905050611150565b604051808460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b61055e61132c565b610566611359565b6003600084815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201600880602002604051908101604052809291908260088015610617576020028201915b815481526020019060010190808311610603575b5050505050815260200160098201600880602002604051908101604052809291908260088015610660576020028201915b81546000191681526020019060010190808311610648575b50505050508152602001601182016080806020026040519081016040528092919082608080156106a9576020028201915b81546000191681526020019060010190808311610691575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016001820154600019166000191681526020016002820154600019166000191681525050815250509050806040015191505b50919050565b6107206113b8565b610728611359565b6003600084815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182016008806020026040519081016040528092919082600880156107d9576020028201915b8154815260200190600101908083116107c5575b5050505050815260200160098201600880602002604051908101604052809291908260088015610822576020028201915b8154600019168152602001906001019080831161080a575b505050505081526020016011820160808060200260405190810160405280929190826080801561086b576020028201915b81546000191681526020019060010190808311610853575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016001820154600019166000191681526020016002820154600019166000191681525050815250509050806020015191505b50919050565b60006108e46113b8565b6108ec61132c565b6108f46113e1565b600060006000610902611359565b600360008a815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182016008806020026040519081016040528092919082600880156109b3576020028201915b81548152602001906001019080831161099f575b50505050508152602001600982016008806020026040519081016040528092919082600880156109fc576020028201915b815460001916815260200190600101908083116109e4575b5050505050815260200160118201608080602002604051908101604052809291908260808015610a45576020028201915b81546000191681526020019060010190808311610a2d575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016001820154600019166000191681526020016002820154600019166000191681525050815250509050806000015197508060200151965080604001519550806060015194508060800151600001519350806080015160200151925080608001516040015191505b50919395979092949650565b6000610afa61140e565b6060604051908101604052808660ff168152602001856000191681526020018460001916815250905060a0604051908101604052808a73ffffffffffffffffffffffffffffffffffffffff16815260200189815260200188815260200187815260200182815250600360008c815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101906008610bd292919061143b565b50604082015181600901906008610bea92919061147b565b50606082015181601101906080610c029291906114c1565b5060808201518160910160008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160010190600019169055604082015181600201906000191690555050905050600191505b5098975050505050505050565b610c6c6113e1565b610c74611359565b6003600084815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201600880602002604051908101604052809291908260088015610d25576020028201915b815481526020019060010190808311610d11575b5050505050815260200160098201600880602002604051908101604052809291908260088015610d6e576020028201915b81546000191681526020019060010190808311610d56575b5050505050815260200160118201608080602002604051908101604052809291908260808015610db7576020028201915b81546000191681526020019060010190808311610d9f575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016001820154600019166000191681526020016002820154600019166000191681525050815250509050806060015191505b50919050565b6000610e30611359565b6003600084815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201600880602002604051908101604052809291908260088015610ee1576020028201915b815481526020019060010190808311610ecd575b5050505050815260200160098201600880602002604051908101604052809291908260088015610f2a576020028201915b81546000191681526020019060010190808311610f12575b5050505050815260200160118201608080602002604051908101604052809291908260808015610f73576020028201915b81546000191681526020019060010190808311610f5b575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016001820154600019166000191681526020016002820154600019166000191681525050815250509050806000015191505b50919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392ff8129836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15156110a657fe5b6102c65a03f115156110b457fe5b50505060405180519050156110eb5760006000815480929190600101919050559050621e847f8111156110e657600090505b6110ff565b600160008154809291906001019190505590505b5b919050565b600061110f6113b8565b61111883610718565b9050600081600060088110151561112b57fe5b6020020151141515611140576001915061114a565b6000915061114a565b5b50919050565b60006000600061115e611359565b6003600086815260200190815260200160002060a060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160088060200260405190810160405280929190826008801561120f576020028201915b8154815260200190600101908083116111fb575b5050505050815260200160098201600880602002604051908101604052809291908260088015611258576020028201915b81546000191681526020019060010190808311611240575b50505050508152602001601182016080806020026040519081016040528092919082608080156112a1576020028201915b81546000191681526020019060010190808311611289575b5050505050815260200160918201606060405190810160405290816000820160009054906101000a900460ff1660ff1660ff16815260200160018201546000191660001916815260200160028201546000191660001916815250508152505090508060800151600001519350806080015160200151925080608001516040015191505b509193909250565b610100604051908101604052806008905b60006000191681526020019060019003908161133d5790505090565b61128060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200161138b611507565b8152602001611398611530565b81526020016113a561155d565b81526020016113b261158a565b81525090565b610100604051908101604052806008905b60008152602001906001900390816113c95790505090565b611000604051908101604052806080905b6000600019168152602001906001900390816113f25790505090565b606060405190810160405280600060ff168152602001600060001916815260200160006000191681525090565b826008810192821561146a579160200282015b8281111561146957825182559160200191906001019061144e565b5b50905061147791906115b7565b5090565b82600881019282156114b0579160200282015b828111156114af57825182906000191690559160200191906001019061148e565b5b5090506114bd91906115dc565b5090565b82608081019282156114f6579160200282015b828111156114f55782518290600019169055916020019190600101906114d4565b5b50905061150391906115dc565b5090565b610100604051908101604052806008905b60008152602001906001900390816115185790505090565b610100604051908101604052806008905b6000600019168152602001906001900390816115415790505090565b611000604051908101604052806080905b60006000191681526020019060019003908161156e5790505090565b606060405190810160405280600060ff168152602001600060001916815260200160006000191681525090565b6115d991905b808211156115d55760008160009055506001016115bd565b5090565b90565b6115fe91905b808211156115fa5760008160009055506001016115e2565b5090565b905600a165627a7a7230582017c9baa56cd21ffbeed32656015bc9ee695ae12bc6f654e6817353d6041ddec20029"; - - private CptData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private CptData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private CptData( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private CptData( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address authorityIssuerDataAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor(Arrays.asList(authorityIssuerDataAddress)); - return deployAsync( - CptData.class, - web3j, - credentials, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue, - Address authorityIssuerDataAddress) { - String encodedConstructor = - FunctionEncoder.encodeConstructor(Arrays.asList(authorityIssuerDataAddress)); - return deployAsync( - CptData.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - encodedConstructor, - initialWeiValue); - } - - public static CptData load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptData(contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - public static CptData load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptData(contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - public static CptData loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptData(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - public static CptData loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CptData(contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - public Future> getCptBytes32Array(Uint256 cptId) { - Function function = - new Function( - "getCptBytes32Array", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future> getCptIntArray(Uint256 cptId) { - Function function = - new Function( - "getCptIntArray", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future> getCpt(Uint256 cptId) { - Function function = - new Function( - "getCpt", - Arrays.asList(cptId), - Arrays.>asList( - new TypeReference

() { - }, - new TypeReference>() { - }, - new TypeReference>() { - }, - new TypeReference>() { - }, - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - return executeCallMultipleValueReturnAsync(function); - } - - public Future putCpt( - Uint256 cptId, - Address cptPublisher, - StaticArray cptIntArray, - StaticArray cptBytes32Array, - StaticArray cptJsonSchemaArray, - Uint8 cptV, - Bytes32 cptR, - Bytes32 cptS) { - Function function = - new Function( - "putCpt", - Arrays.asList( - cptId, - cptPublisher, - cptIntArray, - cptBytes32Array, - cptJsonSchemaArray, - cptV, - cptR, - cptS), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - public void putCpt( - Uint256 cptId, - Address cptPublisher, - StaticArray cptIntArray, - StaticArray cptBytes32Array, - StaticArray cptJsonSchemaArray, - Uint8 cptV, - Bytes32 cptR, - Bytes32 cptS, - TransactionSucCallback callback) { - Function function = - new Function( - "putCpt", - Arrays.asList( - cptId, - cptPublisher, - cptIntArray, - cptBytes32Array, - cptJsonSchemaArray, - cptV, - cptR, - cptS), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - public Future> getCptJsonSchemaArray(Uint256 cptId) { - Function function = - new Function( - "getCptJsonSchemaArray", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference>() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future
getCptPublisher(Uint256 cptId) { - Function function = - new Function( - "getCptPublisher", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference
() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future getCptId(Address publisher) { - Function function = - new Function( - "getCptId", - Arrays.asList(publisher), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future isCptExist(Uint256 cptId) { - Function function = - new Function( - "isCptExist", - Arrays.asList(cptId), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - public Future> getCptSignature(Uint256 cptId) { - Function function = - new Function( - "getCptSignature", - Arrays.asList(cptId), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - return executeCallMultipleValueReturnAsync(function); - } -} diff --git a/src/main/java/com/webank/weid/contract/RoleController.java b/src/main/java/com/webank/weid/contract/RoleController.java deleted file mode 100644 index 926a1b8d..00000000 --- a/src/main/java/com/webank/weid/contract/RoleController.java +++ /dev/null @@ -1,403 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class RoleController extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":true,\"inputs\":[],\"name\":\"MODIFY_ADMIN\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"checkRole\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ROLE_COMMITTEE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"removeRole\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MODIFY_KEY_CPT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"addRole\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"operation\",\"type\":\"uint256\"}],\"name\":\"checkPermission\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MODIFY_AUTHORITY_ISSUER\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MODIFY_COMMITTEE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ROLE_ADMIN\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ROLE_AUTHORITY_ISSUER\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"type\":\"constructor\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b5b6001600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b610905806101266000396000f300606060405236156100ad576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633b20a8c9146100af578063505ef22f146100d5578063793387461461012c57806379db5f67146101525780637b2c0041146101915780637fde1c8a146101b7578063a1a63f65146101f6578063ae23e1751461024d578063c6d8a3f314610273578063d391014b14610299578063f017b58c146102bf575bfe5b34156100b757fe5b6100bf6102e5565b6040518082815260200191505060405180910390f35b34156100dd57fe5b610112600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506102ea565b604051808215151515815260200191505060405180910390f35b341561013457fe5b61013c61040a565b6040518082815260200191505060405180910390f35b341561015a57fe5b61018f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061040f565b005b341561019957fe5b6101a161056d565b6040518082815260200191505060405180910390f35b34156101bf57fe5b6101f4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610572565b005b34156101fe57fe5b610233600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106d0565b604051808215151515815260200191505060405180910390f35b341561025557fe5b61025d6108c5565b6040518082815260200191505060405180910390f35b341561027b57fe5b6102836108ca565b6040518082815260200191505060405180910390f35b34156102a157fe5b6102a96108cf565b6040518082815260200191505060405180910390f35b34156102c757fe5b6102cf6108d4565b6040518082815260200191505060405180910390f35b60ca81565b6000606482141561034957600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050610404565b60658214156103a657600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050610404565b606682141561040357600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050610404565b5b92915050565b606581565b6064811415610482576104233260c86106d0565b15610481576000600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b60658114156104f5576104963260c96106d0565b156104f4576000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b6066811415610568576105093260ca6106d0565b15610567576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b5b5050565b60cb81565b60648114156105e5576105863260c86106d0565b156105e4576001600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b6065811415610658576105f93260c96106d0565b15610657576001600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b60668114156106cb5761066c3260ca6106d0565b156106ca576001600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b5b5050565b600060c882141561078b57600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061077c5750600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b1561078a57600190506108bf565b5b60c98214156107f057600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156107ef57600190506108bf565b5b60ca82141561085557600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561085457600190506108bf565b5b60cb8214156108ba57600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156108b957600190506108bf565b5b600090505b92915050565b60c881565b60c981565b606681565b6064815600a165627a7a72305820f08a5fae2ed2fe140d4fc0f6b4e3aa5c80196bab99534965c17585d375f848a60029"; - - private RoleController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private RoleController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private RoleController( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private RoleController( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue) { - return deployAsync( - RoleController.class, web3j, credentials, gasPrice, gasLimit, BINARY, "", - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue) { - return deployAsync( - RoleController.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - "", - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the role controller - */ - public static RoleController load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new RoleController(contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the role controller - */ - public static RoleController load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new RoleController( - contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the role controller - */ - public static RoleController loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new RoleController(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the role controller - */ - public static RoleController loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new RoleController(contractName, web3j, transactionManager, gasPrice, gasLimit, - true); - } - - /** - * Modify admin. - * - * @return the future - */ - public Future MODIFY_ADMIN() { - Function function = - new Function( - "MODIFY_ADMIN", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Check role. - * - * @param addr the addr - * @param role the role - * @return the future - */ - public Future checkRole(Address addr, Uint256 role) { - Function function = - new Function( - "checkRole", - Arrays.asList(addr, role), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Role committee. - * - * @return the future - */ - public Future ROLE_COMMITTEE() { - Function function = - new Function( - "ROLE_COMMITTEE", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Removes the role. - * - * @param addr the addr - * @param role the role - * @return the future - */ - public Future removeRole(Address addr, Uint256 role) { - Function function = - new Function( - "removeRole", - Arrays.asList(addr, role), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Removes the role. - * - * @param addr the addr - * @param role the role - * @param callback the callback - */ - public void removeRole(Address addr, Uint256 role, TransactionSucCallback callback) { - Function function = - new Function( - "removeRole", - Arrays.asList(addr, role), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Modify key cpt. - * - * @return the future - */ - public Future MODIFY_KEY_CPT() { - Function function = - new Function( - "MODIFY_KEY_CPT", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Adds the role. - * - * @param addr the addr - * @param role the role - * @return the future - */ - public Future addRole(Address addr, Uint256 role) { - Function function = - new Function( - "addRole", Arrays.asList(addr, role), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Adds the role. - * - * @param addr the addr - * @param role the role - * @param callback the callback - */ - public void addRole(Address addr, Uint256 role, TransactionSucCallback callback) { - Function function = - new Function( - "addRole", Arrays.asList(addr, role), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Check permission. - * - * @param addr the addr - * @param operation the operation - * @return the future - */ - public Future checkPermission(Address addr, Uint256 operation) { - Function function = - new Function( - "checkPermission", - Arrays.asList(addr, operation), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Modify authority issuer. - * - * @return the future - */ - public Future MODIFY_AUTHORITY_ISSUER() { - Function function = - new Function( - "MODIFY_AUTHORITY_ISSUER", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Modify committee. - * - * @return the future - */ - public Future MODIFY_COMMITTEE() { - Function function = - new Function( - "MODIFY_COMMITTEE", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Role admin. - * - * @return the future - */ - public Future ROLE_ADMIN() { - Function function = - new Function( - "ROLE_ADMIN", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Role authority issuer. - * - * @return the future - */ - public Future ROLE_AUTHORITY_ISSUER() { - Function function = - new Function( - "ROLE_AUTHORITY_ISSUER", - Arrays.asList(), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } -} diff --git a/src/main/java/com/webank/weid/contract/WeIdContract.java b/src/main/java/com/webank/weid/contract/WeIdContract.java deleted file mode 100644 index 01d09009..00000000 --- a/src/main/java/com/webank/weid/contract/WeIdContract.java +++ /dev/null @@ -1,402 +0,0 @@ -package com.webank.weid.contract; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -import org.bcos.channel.client.TransactionSucCallback; -import org.bcos.web3j.abi.EventEncoder; -import org.bcos.web3j.abi.EventValues; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.Event; -import org.bcos.web3j.abi.datatypes.Function; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.bcos.web3j.protocol.core.methods.request.EthFilter; -import org.bcos.web3j.protocol.core.methods.response.Log; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; -import org.bcos.web3j.tx.TransactionManager; -import rx.Observable; -import rx.functions.Func1; - -/** - * Auto generated code.
Do not modify!
Please use the web3j command line tools, or {@link - * org.bcos.web3j.codegen.SolidityFunctionWrapperGenerator} to update. - * - *

Generated with web3j version none. - */ -public final class WeIdContract extends Contract { - - /** - * The Constant ABI. - */ - public static final String ABI = - "[{\"constant\":true,\"inputs\":[{\"name\":\"identity\",\"type\":\"address\"}],\"name\":\"isIdentityExist\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"identity\",\"type\":\"address\"},{\"name\":\"key\",\"type\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes\"},{\"name\":\"updated\",\"type\":\"int256\"}],\"name\":\"setAttribute\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"identity\",\"type\":\"address\"}],\"name\":\"getLatestRelatedBlock\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"key\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"updated\",\"type\":\"int256\"}],\"name\":\"WeIdAttributeChanged\",\"type\":\"event\"}]"; - - private static String BINARY = - "6060604052341561000c57fe5b5b61041a8061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063170abf9c146100515780633cf239db1461009f5780634298ab941461012e575bfe5b341561005957fe5b610085600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610178565b604051808215151515815260200191505060405180910390f35b34156100a757fe5b61012c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080356000191690602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919080359060200190919050506101f9565b005b341561013657fe5b610162600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103a4565b6040518082815260200191505060405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff166000141580156101e15750600060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600014155b156101ef57600190506101f4565b600090505b919050565b83338173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156102365760006000fd5b8573ffffffffffffffffffffffffffffffffffffffff167fac4dd54786488e78364a1b80c3cb3682c4352995147d8987cbe5210a04261cf48686600060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054876040518085600019166000191681526020018060200184815260200183815260200182810382528581815181526020019150805190602001908083836000831461031a575b80518252602083111561031a576020820191506020810190506020830392506102f6565b505050905090810190601f1680156103465780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a243600060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5b505050505050565b6000600060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b9190505600a165627a7a723058201b7ab5e5bb9720b2c6744299fc4c37ae5218af7f91d970d94a02efb326b037fe0029"; - - private WeIdContract( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, isInitByName); - } - - private WeIdContract( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - Boolean isInitByName) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, isInitByName); - } - - private WeIdContract( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - private WeIdContract( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit, false); - } - - /** - * Gets the WeIdentity DID attribute changed events. - * - * @param transactionReceipt the transaction receipt - * @return the WeIdentity DID attribute changed events - */ - public static List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) { - final Event event = - new Event( - "WeIdAttributeChanged", - Arrays.>asList(new TypeReference

() { - }), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - List valueList = extractEventParameters(event, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValues eventValues : valueList) { - WeIdAttributeChangedEventResponse typedResponse = new WeIdAttributeChangedEventResponse(); - typedResponse.identity = (Address) eventValues.getIndexedValues().get(0); - typedResponse.key = (Bytes32) eventValues.getNonIndexedValues().get(0); - typedResponse.value = (DynamicBytes) eventValues.getNonIndexedValues().get(1); - typedResponse.previousBlock = (Uint256) eventValues.getNonIndexedValues().get(2); - typedResponse.updated = (Int256) eventValues.getNonIndexedValues().get(3); - responses.add(typedResponse); - } - return responses; - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @return the future - */ - public static Future deploy( - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue) { - return deployAsync( - WeIdContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, "", - initialWeiValue); - } - - /** - * Deploy. - * - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @param initialWeiValue the initial wei value - * @return the future - */ - public static Future deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger initialWeiValue) { - return deployAsync( - WeIdContract.class, - web3j, - transactionManager, - gasPrice, - gasLimit, - BINARY, - "", - initialWeiValue); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the WeIdentity DID contract - */ - public static WeIdContract load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new WeIdContract(contractAddress, web3j, credentials, gasPrice, gasLimit, false); - } - - /** - * Load. - * - * @param contractAddress the contract address - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the WeIdentity DID contract - */ - public static WeIdContract load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new WeIdContract(contractAddress, web3j, transactionManager, gasPrice, gasLimit, - false); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param credentials the credentials - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the WeIdentity DID contract - */ - public static WeIdContract loadByName( - String contractName, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new WeIdContract(contractName, web3j, credentials, gasPrice, gasLimit, true); - } - - /** - * Load by name. - * - * @param contractName the contract name - * @param web3j the web3j - * @param transactionManager the transaction manager - * @param gasPrice the gas price - * @param gasLimit the gas limit - * @return the WeIdentity DID contract - */ - public static WeIdContract loadByName( - String contractName, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new WeIdContract(contractName, web3j, transactionManager, gasPrice, gasLimit, true); - } - - /** - * WeIdentity DID attribute changed event observable. - * - * @param startBlock the start block - * @param endBlock the end block - * @return the observable - */ - public Observable weIdAttributeChangedEventObservable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - final Event event = - new Event( - "WeIdAttributeChanged", - Arrays.>asList(new TypeReference
() { - }), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(event)); - return web3j - .ethLogObservable(filter) - .map( - new Func1() { - @Override - public WeIdAttributeChangedEventResponse call(Log log) { - EventValues eventValues = extractEventParameters(event, log); - WeIdAttributeChangedEventResponse typedResponse = - new WeIdAttributeChangedEventResponse(); - typedResponse.identity = (Address) eventValues.getIndexedValues().get(0); - typedResponse.key = (Bytes32) eventValues.getNonIndexedValues().get(0); - typedResponse.value = (DynamicBytes) eventValues.getNonIndexedValues() - .get(1); - typedResponse.previousBlock = (Uint256) eventValues.getNonIndexedValues() - .get(2); - typedResponse.updated = (Int256) eventValues.getNonIndexedValues().get(3); - return typedResponse; - } - }); - } - - /** - * Checks if is identity exist. - * - * @param identity the identity - * @return the future - */ - public Future isIdentityExist(Address identity) { - Function function = - new Function( - "isIdentityExist", - Arrays.asList(identity), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * Sets the attribute. - * - * @param identity the identity - * @param key the key - * @param value the value - * @param updated the updated - * @return the future - */ - public Future setAttribute( - Address identity, Bytes32 key, DynamicBytes value, Int256 updated) { - Function function = - new Function( - "setAttribute", - Arrays.asList(identity, key, value, updated), - Collections.>emptyList()); - return executeTransactionAsync(function); - } - - /** - * Sets the attribute. - * - * @param identity the identity - * @param key the key - * @param value the value - * @param updated the updated - * @param callback the callback - */ - public void setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated, - TransactionSucCallback callback) { - Function function = - new Function( - "setAttribute", - Arrays.asList(identity, key, value, updated), - Collections.>emptyList()); - executeTransactionAsync(function, callback); - } - - /** - * Gets the latest related block. - * - * @param identity the identity - * @return the latest related block - */ - public Future getLatestRelatedBlock(Address identity) { - Function function = - new Function( - "getLatestRelatedBlock", - Arrays.asList(identity), - Arrays.>asList(new TypeReference() { - })); - return executeCallSingleValueReturnAsync(function); - } - - /** - * The Class WeIdAttributeChangedEventResponse. - */ - public static class WeIdAttributeChangedEventResponse { - - /** - * The identity. - */ - public Address identity; - - /** - * The key. - */ - public Bytes32 key; - - /** - * The value. - */ - public DynamicBytes value; - - /** - * The previous block. - */ - public Uint256 previousBlock; - - /** - * The updated. - */ - public Int256 updated; - } -} diff --git a/src/main/java/com/webank/weid/contract/deploy/AddressProcess.java b/src/main/java/com/webank/weid/contract/deploy/AddressProcess.java new file mode 100644 index 00000000..94858389 --- /dev/null +++ b/src/main/java/com/webank/weid/contract/deploy/AddressProcess.java @@ -0,0 +1,142 @@ +package com.webank.weid.contract.deploy; + +import com.webank.weid.config.ContractConfig; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.util.DataToolUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +public abstract class AddressProcess { + /** + * log4j. + */ + private static final Logger logger = LoggerFactory.getLogger(AddressProcess.class); + + protected static void writeAddressToFile( + String contractAddress, + String fileName) { + + OutputStreamWriter ow = null; + try { + boolean flag = true; + File file = new File(fileName); + if (file.exists()) { + flag = file.delete(); + } + if (!flag) { + logger.error("writeAddressToFile() delete file is fail."); + return; + } + ow = new OutputStreamWriter( + new FileOutputStream(fileName, true), + StandardCharsets.UTF_8 + ); + String content = new StringBuffer().append(contractAddress).toString(); + ow.write(content); + ow.close(); + } catch (IOException e) { + logger.error("writer file exception", e); + } finally { + if (ow != null) { + try { + ow.close(); + } catch (IOException e) { + logger.error("io close exception", e); + } + } + } + } + + protected static String getAddressFromFile( + String fileName) { + + BufferedReader br = null; + try { + File file = new File(fileName); + if (file.exists()) { + br = new BufferedReader( + new InputStreamReader(new FileInputStream(file)) + ); + String address = br.readLine(); + return address; + } + } catch (IOException e) { + logger.error("writer file exception", e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + logger.error("io close exception", e); + } + } + } + logger.error("getAddressFromFile() the {} does not exists.", fileName); + return StringUtils.EMPTY; + } + + protected static String getAddress(String fileName) { + String address = getAddressFromFile(fileName); + logger.info("[getAddress] get address from {}, address {}.", fileName, address); + return address; + } + + protected static ContractConfig getContractConfig() { + ContractConfig contractConfig = new ContractConfig(); + String weIdAddress = getAddress("weIdContract.address"); + String issuerAddress = getAddress("authorityIssuer.address"); + String specificAddress = getAddress("specificIssuer.address"); + String evidenceAddress = getAddress("evidenceController.address"); + String cptAddress = getAddress("cptController.address"); + + contractConfig.setWeIdAddress(weIdAddress); + contractConfig.setIssuerAddress(issuerAddress); + contractConfig.setSpecificIssuerAddress(specificAddress); + contractConfig.setEvidenceAddress(evidenceAddress); + contractConfig.setCptAddress(cptAddress); + return contractConfig; + } + + /** + * 根据合约地址获取hash数据. + * @param contractConfig 合约数据 + * @return 返回hash + */ + public static String getHashByAddress(ContractConfig contractConfig) { + String weidAddress = contractConfig.getWeIdAddress(); + String authAddress = contractConfig.getIssuerAddress(); + String specificAddress = contractConfig.getSpecificIssuerAddress(); + String evidenceAddress = contractConfig.getEvidenceAddress(); + String cptAddress = contractConfig.getCptAddress(); + if (StringUtils.isBlank(weidAddress) + || StringUtils.isBlank(authAddress) + || StringUtils.isBlank(specificAddress) + || StringUtils.isBlank(evidenceAddress) + || StringUtils.isBlank(cptAddress)) { + throw new WeIdBaseException("can not found the address, please deploy contract."); + } + StringBuffer address = new StringBuffer(); + address.append(weidAddress) + .append(authAddress) + .append(cptAddress) + .append(specificAddress) + .append(evidenceAddress); + return DataToolUtils.getHash(address.toString()); + } + + /** + * todo 设置String groupId后是否影响hash + * @param groupId groupId + * @param evidenceAddress evidenceAddress + * @return hash + */ + public static String getHashForShare(String groupId, String evidenceAddress) { + StringBuffer address = new StringBuffer(); + address.append("share").append(groupId).append(evidenceAddress); + return DataToolUtils.getHash(address.toString()); + } +} diff --git a/src/main/java/com/webank/weid/contract/deploy/DeployContract.java b/src/main/java/com/webank/weid/contract/deploy/DeployContract.java index 5cb9659c..58bc1358 100644 --- a/src/main/java/com/webank/weid/contract/deploy/DeployContract.java +++ b/src/main/java/com/webank/weid/contract/deploy/DeployContract.java @@ -1,61 +1,19 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.contract.deploy; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +package com.webank.weid.contract.deploy; +import com.webank.weid.constant.ErrorCode; +import com.webank.weid.exception.WeIdBaseException; import org.apache.commons.lang3.StringUtils; -import org.bcos.channel.client.Service; -import org.bcos.contract.tools.ToolConf; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.crypto.GenCredential; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.channel.ChannelEthereumService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import com.webank.weid.constant.WeIdConstant; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.contract.AuthorityIssuerData; -import com.webank.weid.contract.CommitteeMemberController; -import com.webank.weid.contract.CommitteeMemberData; -import com.webank.weid.contract.CptController; -import com.webank.weid.contract.CptData; -import com.webank.weid.contract.RoleController; -import com.webank.weid.contract.WeIdContract; /** * The Class DeployContract. * * @author tonychen */ -public class DeployContract { +public abstract class DeployContract { /** * log4j. @@ -63,28 +21,17 @@ public class DeployContract { private static final Logger logger = LoggerFactory.getLogger(DeployContract.class); /** - * The Constant for default deploy contracts timeout. - */ - private static final Integer DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS = 15; - - /** - * The context. - */ - protected static ApplicationContext context; - - /** - * The credentials. - */ - protected static Credentials credentials; - - /** - * web3j object. - */ - private static Web3j web3j; - - static { - context = new ClassPathXmlApplicationContext("applicationContext.xml"); - } + * The Fisco Config bundle. + */ + //protected static final FiscoConfig fiscoConfig; + + /*static { + fiscoConfig = new FiscoConfig(); + if (!fiscoConfig.load()) { + logger.error("[BaseService] Failed to load Fisco-BCOS blockchain node information."); + System.exit(1); + } + }*/ /** * The main method. @@ -92,256 +39,41 @@ public class DeployContract { * @param args the arguments */ public static void main(String[] args) { - - deployContract(); - System.exit(0); - } - - /** - * Load config. - * - * @return true, if successful - */ - private static boolean loadConfig() { - - Service service = context.getBean(Service.class); - try { - service.run(); - } catch (Exception e) { - logger.error("[BaseService] Service init failed. ", e); - } - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - web3j = Web3j.build(channelEthereumService); - if (null == web3j) { - logger.error("[BaseService] web3j init failed. "); - return false; - } - - ToolConf toolConf = context.getBean(ToolConf.class); - - logger.info("begin init credentials"); - credentials = GenCredential.create(toolConf.getPrivKey()); - - if (null == credentials) { - logger.error("[BaseService] credentials init failed. "); - return false; - } - - return true; - } - - /** - * Gets the web3j. - * - * @return the web3j instance - */ - protected static Web3j getWeb3j() { - if (null == web3j) { - loadConfig(); - } - return web3j; - } - - private static void deployContract() { - String weIdContractAddress = deployWeIDContract(); - String authorityIssuerDataAddress = deployAuthorityIssuerContracts(); - deployCptContracts(authorityIssuerDataAddress, weIdContractAddress); - } - - private static String deployWeIDContract() { - if (null == web3j) { - loadConfig(); - } - Future f = - WeIdContract.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE); - - try { - WeIdContract weIdContract = - f.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - String contractAddress = weIdContract.getContractAddress(); - writeAddressToFile("WeIDContract", contractAddress,"weIdContract.address"); - return contractAddress; - } catch (InterruptedException | ExecutionException | TimeoutException e) { - e.printStackTrace(); + //此处初始化读取main resource的配置文件,可修改chainId为101。并修改fisco.properties:profile.active=prd101 + //String chainId = "101"; + //String chainId = args[0]; + String privateKey = null; + if (args != null && args.length > 2) { + privateKey = args[1]; } - return StringUtils.EMPTY; - } - - private static String deployCptContracts( - String authorityIssuerDataAddress, String weIdContractAddress) { - if (null == web3j) { - loadConfig(); + if (StringUtils.isBlank(privateKey)) { + //privateKey = AddressProcess.getAddressFromFile("ecdsa_key"); + privateKey = AddressProcess.getAddressFromFile("private_key"); } - + //fiscoConfig.setChainId(chainId); + //logger.info("deploy contract fisco version is [{},{}]", fiscoConfig.getVersion(), fiscoConfig.getNodes()); try { - Future f1 = - CptData.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(authorityIssuerDataAddress)); - CptData cptData = f1.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - String cptDataAddress = cptData.getContractAddress(); - // writeAddressToFile("CptData", cptDataAddress); - - Future f2 = - CptController.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(cptDataAddress), - new Address(weIdContractAddress)); - CptController cptController = - f2.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - String cptControllerAddress = cptController.getContractAddress(); - writeAddressToFile("CptController", cptControllerAddress,"cptController.address"); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - e.printStackTrace(); - } - - return StringUtils.EMPTY; - } - - private static String deployAuthorityIssuerContracts() { - if (null == web3j) { - loadConfig(); - } - - // Step 1: Deploy RoleController sol => [addr1] - String authorityIssuerDataAddress = StringUtils.EMPTY; - Future f1 = - RoleController.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE); - - // Step 2: Deploy CommitteeMemberData sol => [addr1] - Future f2 = null; - String roleControllerAddress = StringUtils.EMPTY; - try { - RoleController roleController = - f1.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - roleControllerAddress = roleController.getContractAddress(); - f2 = CommitteeMemberData.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(roleControllerAddress)); - - } catch (Exception e) { - logger.error("RoleController deployment error:" + e.toString()); - return authorityIssuerDataAddress; - } - - // Step 3: Deploy CommitteeMemberController sol => [addr1] - try { - CommitteeMemberData committeeMemberData = - f2.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - String committeeMemberDataAddress = committeeMemberData.getContractAddress(); - - CommitteeMemberController.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(committeeMemberDataAddress), - new Address(roleControllerAddress)); - - } catch (Exception e) { - logger.error("CommitteeMemberData deployment error:" + e.toString()); - return authorityIssuerDataAddress; - } - - // Step 4: Deploy AuthorityIssuerData sol => [addr1] - Future f4 = null; - try { - f4 = AuthorityIssuerData.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(roleControllerAddress)); - - } catch (Exception e) { - logger.error("CommitteeMemberController deployment error:" + e.toString()); - return authorityIssuerDataAddress; - } - - // Step 5: Deploy AuthorityIssuerController sol => [addr1] - Future f5 = null; - try { - AuthorityIssuerData authorityIssuerData = - f4.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - authorityIssuerDataAddress = authorityIssuerData.getContractAddress(); - f5 = AuthorityIssuerController.deploy( - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT, - WeIdConstant.INILITIAL_VALUE, - new Address(authorityIssuerDataAddress), - new Address(roleControllerAddress)); - - } catch (Exception e) { - logger.error("AuthorityIssuerData deployment error:" + e.toString()); - return authorityIssuerDataAddress; - } - - // Step 6: Write [addrress] Into File - try { - AuthorityIssuerController authorityIssuerController = - f5.get(DEFAULT_DEPLOY_CONTRACTS_TIMEOUT_IN_SECONDS, - TimeUnit.SECONDS); - String authorityIssuerControllerAddress = - authorityIssuerController.getContractAddress(); - writeAddressToFile("authorityIssuerController", - authorityIssuerControllerAddress,"authorityIssuer.address"); - return authorityIssuerControllerAddress; - } catch (Exception e) { - logger.error("AuthorityIssuerController deployment error:" + e.toString()); - } - return authorityIssuerDataAddress; - } - - private static void writeAddressToFile(String contractName, String contractAddress, String fileName) { - - FileWriter fileWritter = null; - try { - File file = new File(fileName); - if(file.exists()) { - file.delete(); - } - fileWritter = new FileWriter(fileName, true); - String content = new StringBuffer().append(contractAddress).toString(); - fileWritter.write(content); - fileWritter.close(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (null != fileWritter) { - try { - fileWritter.close(); - } catch (IOException e) { - e.printStackTrace(); - } + com.webank.weid.blockchain.deploy.DeployContract.deployContract(privateKey, true); + } catch (WeIdBaseException e) { + if (e.getErrorCode().getCode() == ErrorCode.CNS_NO_PERMISSION.getCode()) { + System.out.println("deploy fail, Maybe your private key is incorrect. Please make " + + "sure that the root directory of the private key file ecdsa_key that " + + "you deployed for the first time exists in the root directory."); } + throw e; } + System.exit(0); } + + /*public static void deployContract(String privateKey, boolean instantEnable) { + if (fiscoConfig.getVersion().startsWith(WeIdConstant.FISCO_BCOS_1_X_VERSION_PREFIX)) { + throw new WeIdBaseException(ErrorCode.THIS_IS_UNSUPPORTED); + } else if (fiscoConfig.getVersion().startsWith(WeIdConstant.FISCO_BCOS_2_X_VERSION_PREFIX)) { + logger.info("deployContract v2"); + DeployContractV2.deployContract(privateKey, fiscoConfig, instantEnable); + } else if (fiscoConfig.getVersion().startsWith(WeIdConstant.FISCO_BCOS_3_X_VERSION_PREFIX)) { + logger.info("deployContract v3"); + DeployContractV3.deployContract(privateKey, fiscoConfig, instantEnable); + } + }*/ } diff --git a/src/main/java/com/webank/weid/contract/deploy/DeployEvidence.java b/src/main/java/com/webank/weid/contract/deploy/DeployEvidence.java new file mode 100644 index 00000000..34d49840 --- /dev/null +++ b/src/main/java/com/webank/weid/contract/deploy/DeployEvidence.java @@ -0,0 +1,70 @@ + + +package com.webank.weid.contract.deploy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class DeployContract. + * + * @author tonychen + */ +public abstract class DeployEvidence { + + /** + * log4j. + */ + private static final Logger logger = LoggerFactory.getLogger(DeployEvidence.class); + + /** + * The Fisco Config bundle. + */ + /*protected static final FiscoConfig fiscoConfig; + + static { + fiscoConfig = new FiscoConfig(); + if (!fiscoConfig.load()) { + logger.error("[BaseService] Failed to load Fisco-BCOS blockchain node information."); + System.exit(1); + } + }*/ + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + // args = new String[] {"2"}; + + if (args == null || args.length == 0) { + logger.error("input param illegal"); + System.exit(1); + } + + String groupStr = args[0]; + String groupId = groupStr; + + String privateKey = null; + if (args != null && args.length > 1) { + privateKey = args[1]; + } + + com.webank.weid.blockchain.deploy.DeployEvidence.deployContract(privateKey, groupId, true); + System.exit(0); + } + + /** + * 部署evidence合约. + * + * @param privateKey 私钥地址 + * @param groupId 群组编号 + * @param instantEnable 是否即时启用 + * @return 返回部署的hash值 + */ + /*public static String deployContract(String privateKey, String groupId, boolean instantEnable) { + return DeployEvidenceV2.deployContract(fiscoConfig, privateKey, groupId, instantEnable); + }*/ +} diff --git a/src/main/java/com/webank/weid/exception/DataTypeCastException.java b/src/main/java/com/webank/weid/exception/DataTypeCastException.java new file mode 100644 index 00000000..fbc6e22d --- /dev/null +++ b/src/main/java/com/webank/weid/exception/DataTypeCastException.java @@ -0,0 +1,40 @@ + + +package com.webank.weid.exception; + +import com.webank.weid.blockchain.constant.ErrorCode; + +/** + * WeIdBase Exception. Base Exception for WeIdentity Project. + * + * @author tonychen + */ +@SuppressWarnings("serial") +public class DataTypeCastException extends WeIdBaseException { + + + /** + * constructor. + * + * @param cause Throwable + */ + public DataTypeCastException(Throwable cause) { + super(ErrorCode.DATA_TYPE_CASE_ERROR.getCodeDesc(), cause); + } + + /** + * constructor. + * + * @param message message + */ + public DataTypeCastException(String message) { + super(message); + } + + /** + * get associated error code. + */ + public ErrorCode getErrorCode() { + return ErrorCode.DATA_TYPE_CASE_ERROR; + } +} diff --git a/src/main/java/com/webank/weid/exception/DatabaseException.java b/src/main/java/com/webank/weid/exception/DatabaseException.java new file mode 100644 index 00000000..8b716268 --- /dev/null +++ b/src/main/java/com/webank/weid/exception/DatabaseException.java @@ -0,0 +1,40 @@ + + +package com.webank.weid.exception; + +import com.webank.weid.blockchain.constant.ErrorCode; + +/** + * Database Exception. Base Exception for WeIdentity Project. + * + * @author tonychen + */ +@SuppressWarnings("serial") +public class DatabaseException extends WeIdBaseException { + + + /** + * constructor. + * + * @param cause Throwable + */ + public DatabaseException(Throwable cause) { + super(ErrorCode.DATA_TYPE_CASE_ERROR.getCodeDesc(), cause); + } + + /** + * constructor. + * + * @param message message + */ + public DatabaseException(String message) { + super(message); + } + + /** + * get associated error code. + */ + public ErrorCode getErrorCode() { + return ErrorCode.DATA_TYPE_CASE_ERROR; + } +} diff --git a/src/main/java/com/webank/weid/exception/InitWeb3jException.java b/src/main/java/com/webank/weid/exception/InitWeb3jException.java index 02f4c9dc..0386af5b 100644 --- a/src/main/java/com/webank/weid/exception/InitWeb3jException.java +++ b/src/main/java/com/webank/weid/exception/InitWeb3jException.java @@ -1,27 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.exception; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; /** + * InitWeb3sdk Exception. + * * @author tonychen */ @SuppressWarnings("serial") @@ -30,11 +15,15 @@ public class InitWeb3jException extends WeIdBaseException { public InitWeb3jException(Throwable cause) { super(ErrorCode.LOAD_WEB3J_FAILED.getCodeDesc(), cause); } - + + public InitWeb3jException(String message) { + super(message); + } + public InitWeb3jException() { super(ErrorCode.LOAD_WEB3J_FAILED.getCodeDesc()); } - + @Override public ErrorCode getErrorCode() { return ErrorCode.LOAD_WEB3J_FAILED; diff --git a/src/main/java/com/webank/weid/exception/LoadContractException.java b/src/main/java/com/webank/weid/exception/LoadContractException.java index 642d805c..8bbcf9e6 100644 --- a/src/main/java/com/webank/weid/exception/LoadContractException.java +++ b/src/main/java/com/webank/weid/exception/LoadContractException.java @@ -1,27 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.exception; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; /** + * Load Contract Exception. + * * @author tonychen */ @SuppressWarnings("serial") diff --git a/src/main/java/com/webank/weid/exception/LoadKeyStoreException.java b/src/main/java/com/webank/weid/exception/LoadKeyStoreException.java new file mode 100644 index 00000000..6a293833 --- /dev/null +++ b/src/main/java/com/webank/weid/exception/LoadKeyStoreException.java @@ -0,0 +1,25 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.exception; + +/** Exceptioned when calling KeyManager. */ +public class LoadKeyStoreException extends RuntimeException { + public LoadKeyStoreException(String message) { + super(message); + } + + public LoadKeyStoreException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/webank/weid/exception/PrivateKeyIllegalException.java b/src/main/java/com/webank/weid/exception/PrivateKeyIllegalException.java index 40669cdf..5fc6e856 100644 --- a/src/main/java/com/webank/weid/exception/PrivateKeyIllegalException.java +++ b/src/main/java/com/webank/weid/exception/PrivateKeyIllegalException.java @@ -1,27 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.exception; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; /** + * Private Key IllegalException. + * * @author tonychen */ @SuppressWarnings("serial") diff --git a/src/main/java/com/webank/weid/exception/SaveKeyStoreException.java b/src/main/java/com/webank/weid/exception/SaveKeyStoreException.java new file mode 100644 index 00000000..86eced13 --- /dev/null +++ b/src/main/java/com/webank/weid/exception/SaveKeyStoreException.java @@ -0,0 +1,25 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.exception; + +/** Exceptioned when save the CryptoKeyPair into p12 or pem */ +public class SaveKeyStoreException extends RuntimeException { + public SaveKeyStoreException(String message) { + super(message); + } + + public SaveKeyStoreException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/webank/weid/exception/WeIdBaseException.java b/src/main/java/com/webank/weid/exception/WeIdBaseException.java index b3ef341c..98562e99 100644 --- a/src/main/java/com/webank/weid/exception/WeIdBaseException.java +++ b/src/main/java/com/webank/weid/exception/WeIdBaseException.java @@ -1,55 +1,55 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.exception; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; /** - * @author tonychen Base Exception for WeIdentity Project + * WeIdBase Exception. Base Exception for WeIdentity Project. + * + * @author tonychen */ @SuppressWarnings("serial") public class WeIdBaseException extends RuntimeException { + + private ErrorCode errorCode = ErrorCode.BASE_ERROR; /** - * constructor + * constructor. * * @param msg exception message + * @param cause exception object */ public WeIdBaseException(String msg, Throwable cause) { super(msg, cause); } /** - * constructor + * constructor. * * @param msg exception message */ public WeIdBaseException(String msg) { super(msg); } + + /** + * constructor. + * + * @param errorCode the errorCode + */ + public WeIdBaseException(ErrorCode errorCode) { + this(errorCode.getCode() + " - " + errorCode.getCodeDesc()); + this.errorCode = errorCode; + } /** - * get associated error code + * get associated error code. + * + * @return ErrorCode */ public ErrorCode getErrorCode() { - return ErrorCode.BASE_ERROR; + return errorCode; } @Override @@ -58,7 +58,7 @@ public String toString() { StringBuilder builder = new StringBuilder(); builder .append(s) - .append(". Error code =") + .append(". Error code = ") .append(getErrorCode().getCode()) .append(", Error message : ") .append(getMessage()); diff --git a/src/main/java/com/webank/weid/protocol/base/AuthenticationProperty.java b/src/main/java/com/webank/weid/protocol/base/AuthenticationProperty.java index 1b84a5fe..081a4295 100644 --- a/src/main/java/com/webank/weid/protocol/base/AuthenticationProperty.java +++ b/src/main/java/com/webank/weid/protocol/base/AuthenticationProperty.java @@ -1,25 +1,13 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.Multibase.Multibase; +import com.webank.weid.util.Multicodec.DecodedData; +import com.webank.weid.util.Multicodec.MulticodecEncoder; import lombok.Data; +import org.fisco.bcos.sdk.model.CryptoType; /** * The base data structure for AuthenticationProperty. @@ -30,12 +18,59 @@ public class AuthenticationProperty { /** - * Required: The type. + * Required: The verification method id. + */ + private String id; + + /** + * Required: The verification method type. */ - private String type = "Secp256k1SignatureAuthentication2018"; + private String type = DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? "Ed25519VerificationKey2020":"SM2VerificationKey"; /** - * Required: The public key. + * Required: The verification method controller. */ - private String publicKey; + private String controller; + + /** + * Required: The verification method material. + */ + private String publicKeyMultibase; + + public String toString() { + return this.id + ',' + this.type + ',' + this.controller + ',' + this.publicKeyMultibase; + } + + public static AuthenticationProperty fromString(String authString) { + String[] result = authString.split(","); + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + authenticationProperty.setId(result[0]); + authenticationProperty.setController(result[2]); + authenticationProperty.setPublicKeyMultibase(result[3]); + return authenticationProperty; + } + + public String getPublicKey() { + byte[] publicKeyEncode = Multibase.decode(this.publicKeyMultibase); + DecodedData decodedData = MulticodecEncoder.decode(publicKeyEncode); + return new String(decodedData.getData()); + } + + public static AuthenticationProperty fromBlockChain(com.webank.weid.blockchain.protocol.base.AuthenticationProperty authentication) { + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + authenticationProperty.setType(authentication.getType()); + authenticationProperty.setController(authentication.getController()); + authenticationProperty.setId(authentication.getId()); + authenticationProperty.setPublicKeyMultibase(authentication.getPublicKeyMultibase()); + return authenticationProperty; + } + + public static com.webank.weid.blockchain.protocol.base.AuthenticationProperty toBlockChain(AuthenticationProperty authentication) { + com.webank.weid.blockchain.protocol.base.AuthenticationProperty authenticationProperty = new com.webank.weid.blockchain.protocol.base.AuthenticationProperty(); + authenticationProperty.setType(authentication.getType()); + authenticationProperty.setController(authentication.getController()); + authenticationProperty.setId(authentication.getId()); + authenticationProperty.setPublicKeyMultibase(authentication.getPublicKeyMultibase()); + return authenticationProperty; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/AuthorityIssuer.java b/src/main/java/com/webank/weid/protocol/base/AuthorityIssuer.java index dcfe9c70..86993801 100644 --- a/src/main/java/com/webank/weid/protocol/base/AuthorityIssuer.java +++ b/src/main/java/com/webank/weid/protocol/base/AuthorityIssuer.java @@ -1,25 +1,16 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.util.DateUtils; /** * The base data structure to handle Authority Issuer info. @@ -48,4 +39,90 @@ public class AuthorityIssuer { * Required: The accumulator value of the Authority Issuer. */ private String accValue; + + /** + * Optional: The description of this Authority Issuer. + */ + private String description; + + /** + * Optional: The extra String type information stored on chain. + */ + private List extraStr32; + + /** + * Optional: The extra Integer type information stored on chain. + */ + private List extraInt; + + /** + * Optional: whether this authority issuer is recognized by admin/committee, or not. + */ + private boolean recognized = false; + + /** + * Constructor with initialized values. + * + * @param weId the WeID + * @param name the name + * @param accValue the accumulator value (currently unused) + * @param description the description + * @param extraStr32 the extra String list + * @param extraInt the extra Integer list + */ + public AuthorityIssuer( + String weId, + String name, + String accValue, + String description, + List extraStr32, + List extraInt + ) { + this.weId = weId; + this.name = name; + this.created = DateUtils.getNoMillisecondTimeStamp(); + this.accValue = accValue; + this.description = StringUtils.isEmpty(description) ? StringUtils.EMPTY : description; + this.extraStr32 = extraStr32 == null ? new ArrayList<>() : extraStr32; + this.extraInt = extraInt == null ? new ArrayList<>() : extraInt; + } + + /** + * Empty Constructor. + */ + public AuthorityIssuer() { + this.weId = StringUtils.EMPTY; + this.name = StringUtils.EMPTY; + this.created = DateUtils.getNoMillisecondTimeStamp(); + this.accValue = StringUtils.EMPTY; + this.description = StringUtils.EMPTY; + this.extraStr32 = new ArrayList<>(); + this.extraInt = new ArrayList<>(); + } + + public static com.webank.weid.blockchain.protocol.base.AuthorityIssuer toBlockChain(AuthorityIssuer issuer) { + com.webank.weid.blockchain.protocol.base.AuthorityIssuer authorityIssuer = new com.webank.weid.blockchain.protocol.base.AuthorityIssuer(); + authorityIssuer.setWeId(issuer.getWeId()); + authorityIssuer.setName(issuer.getName()); + authorityIssuer.setCreated(issuer.getCreated()); + authorityIssuer.setAccValue(issuer.getAccValue()); + authorityIssuer.setDescription(issuer.getDescription()); + authorityIssuer.setExtraInt(issuer.getExtraInt()); + authorityIssuer.setExtraStr32(issuer.getExtraStr32()); + authorityIssuer.setRecognized(issuer.isRecognized()); + return authorityIssuer; + } + + public static AuthorityIssuer fromBlockChain(com.webank.weid.blockchain.protocol.base.AuthorityIssuer issuer) { + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId(issuer.getWeId()); + authorityIssuer.setName(issuer.getName()); + authorityIssuer.setCreated(issuer.getCreated()); + authorityIssuer.setAccValue(issuer.getAccValue()); + authorityIssuer.setDescription(issuer.getDescription()); + authorityIssuer.setExtraInt(issuer.getExtraInt()); + authorityIssuer.setExtraStr32(issuer.getExtraStr32()); + authorityIssuer.setRecognized(issuer.isRecognized()); + return authorityIssuer; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/Challenge.java b/src/main/java/com/webank/weid/protocol/base/Challenge.java new file mode 100644 index 00000000..2928477a --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/Challenge.java @@ -0,0 +1,100 @@ + + +package com.webank.weid.protocol.base; + +import java.security.SecureRandom; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.protocol.inf.RawSerializer; +import com.webank.weid.util.DataToolUtils; + +/** + * Created by Junqi Zhang on 2019/4/9. + */ +@Getter +@Setter +public class Challenge extends Version implements RawSerializer { + + private static final Logger logger = LoggerFactory.getLogger(Challenge.class); + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = 3783172794625195471L; + + /** + * Specify who you want to challenge. + */ + private String weId; + + /** + * Specify a random alphanumeric nonce and WeIdentity DID owner will sign a credential which + * include the nonce to prove the ownership of this WeIdentity DID. The relying party should + * include a random alphanumeric (i.e. nonce) in the challenge, to prevent replay attacks. This + * is also known as dynamic challenge. + * + */ + private String nonce; + + /** + * Factory function which can help to create a brand new challenge object. + * + * @param userWeId Specify who you want to challenge. Most of the time you need to pass user's + * weId. + * @param seed the verify seed + * @return Challenge + */ + public static Challenge create(String userWeId, String seed) { + + SecureRandom random = new SecureRandom(); + String randomSeed = seed + DataToolUtils.getUuId32(); + random.setSeed(randomSeed.getBytes()); + byte[] bytes = new byte[15]; + random.nextBytes(bytes); + String nonce = Base64.encodeBase64String(bytes); + + Challenge challenge = new Challenge(); + challenge.setNonce(nonce); + challenge.setWeId(userWeId); + return challenge; + } + + @Override + public String toJson() { + return DataToolUtils.addTagFromToJson(DataToolUtils.serialize(this)); + } + + /** + * create Challenge with JSON String. + * @param challengeJson the challenge JSON String + * @return Challenge + */ + public static Challenge fromJson(String challengeJson) { + if (StringUtils.isBlank(challengeJson)) { + logger.error("create Challenge with JSON String failed, " + + "the Challenge JSON String is null"); + throw new DataTypeCastException("the Challenge JSON String is null."); + } + String challengeString = challengeJson; + if (DataToolUtils.isValidFromToJson(challengeJson)) { + challengeString = DataToolUtils.removeTagFromToJson(challengeJson); + } + return DataToolUtils.deserialize(challengeString, Challenge.class); + } + + @Override + public String toRawData() { + return this.nonce; + } + + private Challenge() { + this.setVersion(1); + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/ClaimPolicy.java b/src/main/java/com/webank/weid/protocol/base/ClaimPolicy.java new file mode 100644 index 00000000..a49d3145 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/ClaimPolicy.java @@ -0,0 +1,16 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Data; + +/** + * The base data structure to handle Credential info. + * + * @author junqizhang 2019.04 + */ +@Data +public class ClaimPolicy { + + private String fieldsToBeDisclosed; +} diff --git a/src/main/java/com/webank/weid/protocol/base/ClaimPolicyBaseInfo.java b/src/main/java/com/webank/weid/protocol/base/ClaimPolicyBaseInfo.java new file mode 100644 index 00000000..070e25d8 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/ClaimPolicyBaseInfo.java @@ -0,0 +1,24 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Data; + +/** + * The base data structure for the SDK API register CPT info. + * + * @author junqizhang + */ +@Data +public class ClaimPolicyBaseInfo { + + /** + * Required: The id for the CPT. + */ + private Integer claimPolicyId; + + /** + * Required: The version of the CPT for the same CPT id. + */ + private Integer claimPolicyVersion; +} diff --git a/src/main/java/com/webank/weid/protocol/base/Cpt.java b/src/main/java/com/webank/weid/protocol/base/Cpt.java index 8a84c5fd..32206a0b 100644 --- a/src/main/java/com/webank/weid/protocol/base/Cpt.java +++ b/src/main/java/com/webank/weid/protocol/base/Cpt.java @@ -1,30 +1,17 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; +import java.util.HashMap; +import java.util.Map; + +import com.webank.weid.protocol.response.RsvSignature; import lombok.Data; /** * The base data structure for the CPT. * - * @author lingfenghe + * @author junqizhang */ @Data public class Cpt { @@ -32,17 +19,17 @@ public class Cpt { /** * Base info of cpt. */ - private CptBaseInfo cptBaseInfo = new CptBaseInfo(); + protected CptBaseInfo cptBaseInfo = new CptBaseInfo(); /** * The cpt json schema. */ - private String cptJsonSchema; + protected Map cptJsonSchema; /** * The meta data. */ - private MetaData metaData = new MetaData(); + protected MetaData metaData = new MetaData(); /** * Gets the cpt id. @@ -152,11 +139,24 @@ public void setUpdated(long updated) { metaData.setUpdated(updated); } + /** + * transfer cpt MetaData from weid-blockchain. + * @param cptData the cpt MetaData class in weid-blockchain + * @return RsvSignature + */ + public static Cpt fromBlockChain(com.webank.weid.blockchain.protocol.base.Cpt cptData) { + Cpt cpt = new Cpt(); + cpt.setCptBaseInfo(CptBaseInfo.fromBlockChain(cptData.getCptBaseInfo())); + cpt.setCptJsonSchema(cptData.getCptJsonSchema()); + cpt.setMetaData(MetaData.fromBlockChain(cptData.getMetaData())); + return cpt; + } + /** * The base data structure for CPT meta data. */ @Data - public class MetaData { + public static class MetaData { /** * The weIdentity DID of the publisher who register this CPT. @@ -177,5 +177,19 @@ public class MetaData { * The cpt update timestamp. */ private long updated; + + /** + * transfer cpt MetaData from weid-blockchain. + * @param data the cpt MetaData class in weid-blockchain + * @return RsvSignature + */ + public static MetaData fromBlockChain(com.webank.weid.blockchain.protocol.base.Cpt.MetaData data) { + MetaData metaData = new MetaData(); + metaData.setUpdated(data.getUpdated()); + metaData.setCreated(data.getCreated()); + metaData.setCptSignature(data.getCptSignature()); + metaData.setCptPublisher(data.getCptPublisher()); + return metaData; + } } } diff --git a/src/main/java/com/webank/weid/protocol/base/CptBaseInfo.java b/src/main/java/com/webank/weid/protocol/base/CptBaseInfo.java index 42775b45..e8736a96 100644 --- a/src/main/java/com/webank/weid/protocol/base/CptBaseInfo.java +++ b/src/main/java/com/webank/weid/protocol/base/CptBaseInfo.java @@ -1,26 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; import lombok.Data; +import java.util.ArrayList; +import java.util.List; + /** * The base data structure for the SDK API register CPT info. * @@ -38,4 +24,16 @@ public class CptBaseInfo { * Required: The version of the CPT for the same CPT id. */ private Integer cptVersion; + + /** + * transfer the CptBaseInfo from weid-blockchain. + * @param cpt the CptBaseInfo class in weid-blockchain + * @return WeIdDocument + */ + public static CptBaseInfo fromBlockChain(com.webank.weid.blockchain.protocol.base.CptBaseInfo cpt) { + CptBaseInfo cptBaseInfo = new CptBaseInfo(); + cptBaseInfo.setCptId(cpt.getCptId()); + cptBaseInfo.setCptVersion(cpt.getCptVersion()); + return cptBaseInfo; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/Credential.java b/src/main/java/com/webank/weid/protocol/base/Credential.java index d28f7d8a..424d7432 100644 --- a/src/main/java/com/webank/weid/protocol/base/Credential.java +++ b/src/main/java/com/webank/weid/protocol/base/Credential.java @@ -1,25 +1,16 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; +import java.util.Map; + import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.protocol.inf.Hashable; +import com.webank.weid.util.CredentialUtils; /** * The base data structure to handle Credential info. @@ -27,7 +18,7 @@ * @author chaoxinhu 2018.10 */ @Data -public class Credential { +public class Credential implements Hashable { /** * Required: The context field. @@ -52,7 +43,7 @@ public class Credential { /** * Required: The create date. */ - private Long issuranceDate; + private Long issuanceDate; /** * Required: The expire date. @@ -62,11 +53,56 @@ public class Credential { /** * Required: The claim data. */ - private String claim; + private Map claim; + + /** + * Required: The credential proof data. + */ + private Map proof; + + /** + * Directly extract the signature value from credential. + * + * @return signature value + */ + public String getSignature() { + return getValueFromProof(ParamKeyConstant.CREDENTIAL_SIGNATURE); + } + + /** + * Directly extract the proof type from credential. + * + * @return proof type + */ + public String getProofType() { + return getValueFromProof(ParamKeyConstant.PROOF_TYPE); + } + + private String getValueFromProof(String key) { + if (proof != null) { + return proof.get(key); + } + return StringUtils.EMPTY; + } + + /** + * Get the unique hash value of this Credential. + * + * @return hash value + */ + public String getHash() { + if (CredentialUtils.isCredentialValid(this) != ErrorCode.SUCCESS) { + return StringUtils.EMPTY; + } + return CredentialUtils.getCredentialHash(this); + } /** - * Required: The signature of the Credential. Selective Disclosure is supported together with - * Claim Data structure. + * Get the signature thumbprint for re-signing. + * + * @return thumbprint */ - private String signature; + public String getSignatureThumbprint() { + return CredentialUtils.getCredentialThumbprint(this, null); + } } diff --git a/src/main/java/com/webank/weid/protocol/base/CredentialPojo.java b/src/main/java/com/webank/weid/protocol/base/CredentialPojo.java new file mode 100644 index 00000000..8727b329 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/CredentialPojo.java @@ -0,0 +1,287 @@ + + +package com.webank.weid.protocol.base; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.CredentialType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.protocol.inf.Hashable; +import com.webank.weid.protocol.inf.IProof; +import com.webank.weid.protocol.inf.JsonSerializer; +import com.webank.weid.util.CredentialPojoUtils; +import com.webank.weid.util.DataToolUtils; + + +/** + * The base data structure to handle Credential info. + * + * @author junqizhang 2019.04 + */ +@Data +public class CredentialPojo implements IProof, JsonSerializer, Hashable { + + private static final Logger logger = LoggerFactory.getLogger(CredentialPojo.class); + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = 8197843857223846978L; + + /** + * Required: The context field. + */ + private String context; + + /** + * Required: The ID. + */ + private String id; + + /** + * Required: The CPT type in standard integer format. + */ + private Integer cptId; + + /** + * Required: The issuer WeIdentity DID. + */ + private String issuer; + + /** + * Required: The create date. + */ + private Long issuanceDate; + + /** + * Required: The expire date. + */ + private Long expirationDate; + + /** + * Required: The claim data. + */ + private Map claim; + + /** + * Required: The credential proof data. + */ + private Map proof; + + /** + * Required: The credential type default is VerifiableCredential. + */ + private List type; + + /** + * create CredentialPojo with JSON String. + * + * @param credentialJson the CredentialPojo JSON String + * @return CredentialPojo + */ + public static CredentialPojo fromJson(String credentialJson) { + if (StringUtils.isBlank(credentialJson)) { + logger.error("create credential with JSON String failed, " + + "the credential JSON String is null"); + throw new DataTypeCastException("the credential JSON String is null"); + } + + String credentialString = credentialJson; + if (DataToolUtils.isValidFromToJson(credentialJson)) { + credentialString = DataToolUtils.removeTagFromToJson(credentialJson); + } + Map credentialMap = DataToolUtils + .deserialize(credentialString, HashMap.class); + + Object type = credentialMap.get(ParamKeyConstant.PROOF_TYPE); + + //lite1类型的credential要做特殊处理,将廋身过的json还原成可验证的lite credential对象 + if (type instanceof String && StringUtils + .equals(String.valueOf(type), CredentialType.LITE1.getName())) { + //result.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + String signature = String.valueOf(credentialMap.get(ParamKeyConstant.PROOF)); + credentialMap.remove(ParamKeyConstant.PROOF_TYPE); + credentialMap.remove(ParamKeyConstant.PROOF); + CredentialPojo credentialPojo; + try { + credentialPojo = DataToolUtils.mapToObj( + credentialMap, + CredentialPojo.class + ); + credentialPojo.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + //credentialPojo.setIssuanceDate(0L); + credentialPojo.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + credentialPojo.addType(CredentialType.LITE1.getName()); + return credentialPojo; + } catch (Exception e) { + logger.error("[fromJson] deserialize failed. error message:{}", e); + return null; + } + + } + CredentialPojo credentialPojo = DataToolUtils.deserialize( + DataToolUtils.convertUtcToTimestamp(credentialString), + CredentialPojo.class + ); + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + logger.error("create CredentialPojo with JSON String failed, {}", + checkResp.getCodeDesc()); + throw new DataTypeCastException(checkResp.getCodeDesc()); + } + if (!CredentialPojoUtils.validClaimAndSaltForMap( + credentialPojo.getClaim(), + credentialPojo.getSalt())) { + logger.error("create PresentationE with JSON String failed, claim and salt of " + + "credentialPojo not match."); + throw new DataTypeCastException("claim and salt of credentialPojo not match."); + } + return credentialPojo; + } + + /** + * 添加type. + * + * @param typeValue the typeValue + */ + public void addType(String typeValue) { + if (type == null) { + type = new ArrayList(); + } + type.add(typeValue); + } + + /** + * Directly extract the signature value from credential. + * + * @return signature value + */ + public String getSignature() { + return toString(getValueFromProof(proof, ParamKeyConstant.PROOF_SIGNATURE)); + } + + /** + * Directly extract the proof type from credential. + * + * @return proof type + */ + public String getProofType() { + return toString(getValueFromProof(proof, ParamKeyConstant.PROOF_TYPE)); + } + + /** + * Directly extract the salt from credential. + * + * @return salt + */ + public Map getSalt() { + return (Map) getValueFromProof(proof, ParamKeyConstant.PROOF_SALT); + } + + /** + * put the salt into proof. + * + * @param salt map of salt + */ + public void setSalt(Map salt) { + putProofValue(ParamKeyConstant.PROOF_SALT, salt); + } + + /** + * put the key-value into proof. + * + * @param key the key of proof + * @param value the value of proof + */ + public void putProofValue(String key, Object value) { + if (proof == null) { + proof = new HashMap<>(); + } + proof.put(key, value); + } + + /** + * convert CredentialPojo to JSON String. + * + * @return CredentialPojo + */ + @Override + public String toJson() { + + //如果是LITE1类型的credential,则需要廋身 + if (type.contains(CredentialType.LITE1.getName())) { + try { + String signature = this.getSignature(); + Map credMap = DataToolUtils.objToMap(this); + //credMap.remove(ParamKeyConstant.ISSUANCE_DATE); + credMap.remove(ParamKeyConstant.CONTEXT); + credMap.remove(ParamKeyConstant.PROOF); + credMap.put(ParamKeyConstant.PROOF_TYPE, CredentialType.LITE1.getName()); + + credMap.put(ParamKeyConstant.PROOF, signature); + return DataToolUtils.serialize(credMap); + } catch (Exception e) { + logger.error("[CredentialPojo:toJson] failed, error message:{}", e); + return StringUtils.EMPTY; + } + } + String json = DataToolUtils.convertTimestampToUtc(DataToolUtils.serialize(this)); + return DataToolUtils.addTagFromToJson(json); + } + + /** + * Generate the unique hash of this CredentialPojo. + * + * @return hash value + */ + public String getHash() { + if (type.contains(CredentialType.LITE1.getName())) { + return CredentialPojoUtils.getLiteCredentialPojoHash(this); + } + if (CredentialPojoUtils.isCredentialPojoValid(this) != ErrorCode.SUCCESS) { + return StringUtils.EMPTY; + } + return CredentialPojoUtils.getCredentialPojoHash(this, null); + } + + /** + * Get the signature thumbprint for re-signing. + * + * @return thumbprint + */ + public String getSignatureThumbprint() { + return CredentialPojoUtils.getCredentialThumbprintWithoutSig(this, this.getSalt(), null); + } + + /** + * Get the CredentialType. + * @return the CredentialType + */ + public CredentialType getCredentialType() { + if (this.type == null) { + logger.warn("[getCredentialType] the type is null."); + return null; + } + if (this.type.contains(CredentialType.ZKP.getName())) { + return CredentialType.ZKP; + } else if (this.type.contains(CredentialType.LITE1.getName())) { + return CredentialType.LITE1; + } else if (this.type.contains(CredentialType.ORIGINAL.getName())) { + return CredentialType.ORIGINAL; + } else { + logger.warn("[getCredentialType] the type does not contain default CredentialType."); + return null; + } + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/CredentialPojoList.java b/src/main/java/com/webank/weid/protocol/base/CredentialPojoList.java new file mode 100644 index 00000000..4e197c97 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/CredentialPojoList.java @@ -0,0 +1,55 @@ + + +package com.webank.weid.protocol.base; + +import com.webank.weid.util.DataToolUtils; +import java.io.IOException; +import java.util.ArrayList; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.protocol.inf.JsonSerializer; + +public class CredentialPojoList extends ArrayList implements JsonSerializer { + + private static final Logger logger = LoggerFactory.getLogger(CredentialPojoList.class); + + /** + * the serial. + */ + private static final long serialVersionUID = -6164771401868673728L; + + @Override + public String toJson() { + StringBuffer buffer = new StringBuffer(); + buffer.append("["); + for (CredentialPojo credential : this) { + buffer.append(credential.toJson()).append(","); + } + buffer.deleteCharAt(buffer.length() - 1); + buffer.append("]"); + return buffer.toString(); + } + + /** + * 将Json转换成CredentialPojoList. + * + * @param json json数据 + * @return 返回CredentialPojoList + */ + public static CredentialPojoList fromJson(String json) { + try { + JsonNode jsonNode = DataToolUtils.loadJsonObject(json); + ArrayNode arrayNode = (ArrayNode)jsonNode; + CredentialPojoList result = new CredentialPojoList(); + arrayNode.forEach(node -> result.add(CredentialPojo.fromJson(node.toString()))); + return result; + } catch (IOException e) { + logger.info("[fromJson] from JSON error for CredentialPojoList.", e); + return null; + } + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/CredentialWrapper.java b/src/main/java/com/webank/weid/protocol/base/CredentialWrapper.java new file mode 100644 index 00000000..0572571c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/CredentialWrapper.java @@ -0,0 +1,69 @@ + + +package com.webank.weid.protocol.base; + +import java.util.Map; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.protocol.inf.Hashable; +import com.webank.weid.util.CredentialUtils; + +/** + * Credential response. + * + * @author tonychen 2019年1月24日 + */ +@Data +public class CredentialWrapper implements Hashable { + + /** + * Required: The Credential. + */ + private Credential credential; + + /** + * Required: key is the credential field, and value "1" for disclosure to the third party, "0" + * for no disclosure. + */ + private Map disclosure; + + /** + * Generate the unique hash of this CredentialWrapper. + * + * @return hash value + */ + public String getHash() { + if (this == null) { + return StringUtils.EMPTY; + } + if (this.getDisclosure() == null || this.getDisclosure().size() == 0) { + return this.getCredential().getHash(); + } + Credential credential = this.getCredential(); + if (CredentialUtils.isCredentialValid(credential) != ErrorCode.SUCCESS) { + return StringUtils.EMPTY; + } + return CredentialUtils.getCredentialWrapperHash(this); + } + + /** + * Directly extract the signature value from credential. + * + * @return signature value + */ + public String getSignature() { + return credential.getSignature(); + } + + /** + * Get the signature thumbprint for re-signing. + * + * @return thumbprint + */ + public String getSignatureThumbprint() { + return CredentialUtils.getCredentialThumbprint(this.getCredential(), this.getDisclosure()); + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/EvidenceInfo.java b/src/main/java/com/webank/weid/protocol/base/EvidenceInfo.java new file mode 100644 index 00000000..537c213c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/EvidenceInfo.java @@ -0,0 +1,72 @@ + + +package com.webank.weid.protocol.base; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.Data; + +/** + * The base data structure to handle Credential EvidenceInfo info. + * + * @author chaoxinhu 2019.1 + */ +@Data +public class EvidenceInfo { + + /** + * Required: full Credential hash. + */ + private String credentialHash; + + /** + * Required: sign info mapping (key: signer WeID, value: evidenceSignInfo). + */ + private Map signInfo = new HashMap<>(); + + /** + * Get all signers info. + * + * @return signers list + */ + public List getSigners() { + List signers = new ArrayList<>(); + for (Map.Entry entry : signInfo.entrySet()) { + signers.add(entry.getKey()); + } + return signers; + } + + /** + * Get all signatures info. + * + * @return signatures list + */ + public List getSignatures() { + List signatures = new ArrayList<>(); + for (Map.Entry entry : signInfo.entrySet()) { + signatures.add(entry.getValue().getSignature()); + } + return signatures; + } + + /** + * change EvidenceInfo from weid-blockchain. + * @param evidence the weid-blockchain evidence class + * @return EvidenceInfo + */ + public static EvidenceInfo fromBlockChain(com.webank.weid.blockchain.protocol.base.EvidenceInfo evidence) { + EvidenceInfo evidenceInfo = new EvidenceInfo(); + evidenceInfo.setCredentialHash(evidence.getCredentialHash()); + Map signInfoMap = new HashMap<>(); + for(Map.Entry entry : evidence.getSignInfo().entrySet()){ + EvidenceSignInfo evidenceSignInfo = EvidenceSignInfo.fromBlockChain(entry.getValue()); + signInfoMap.put(entry.getKey(), evidenceSignInfo); + } + evidenceInfo.setSignInfo(signInfoMap); + return evidenceInfo; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/EvidenceSignInfo.java b/src/main/java/com/webank/weid/protocol/base/EvidenceSignInfo.java new file mode 100644 index 00000000..e191c003 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/EvidenceSignInfo.java @@ -0,0 +1,49 @@ + + +package com.webank.weid.protocol.base; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +/** + * The sign information of evidence's each signer's sign attempt. Used as a mapped info against each + * individual signer. + * + * @author chaoxinhu 2020.2 + * @since v1.6.0 + */ +@Data +public class EvidenceSignInfo { + + /** + * The signature of the signer onto this evidence. + */ + private String signature; + + /** + * The timestamp at which this evidence is signed. + */ + private String timestamp; + + /** + * The extra value this signer records on chain. + */ + private List logs = new ArrayList<>(); + + /** + * Whether this signer revoked this evidence. This is initialized as null, and will be set + * appropriate values upon getEvidence(). + */ + private Boolean revoked = null; + + public static EvidenceSignInfo fromBlockChain(com.webank.weid.blockchain.protocol.base.EvidenceSignInfo evidenceSign) { + EvidenceSignInfo evidenceSignInfo = new EvidenceSignInfo(); + evidenceSignInfo.setSignature(evidenceSign.getSignature()); + evidenceSignInfo.setTimestamp(evidenceSign.getTimestamp()); + evidenceSignInfo.setRevoked(evidenceSign.getRevoked()); + evidenceSignInfo.setLogs(evidenceSign.getLogs()); + return evidenceSignInfo; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/GlobalStatus.java b/src/main/java/com/webank/weid/protocol/base/GlobalStatus.java new file mode 100644 index 00000000..472f6a64 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/GlobalStatus.java @@ -0,0 +1,71 @@ +package com.webank.weid.protocol.base; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.webank.weid.blockchain.protocol.inf.JsonSerializer; +import com.webank.weid.contract.deploy.AddressProcess; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + + +/** + * The class of global status for running locally with database. + * + * @author afeexian + */ +@Data +public class GlobalStatus implements JsonSerializer { + + private static final Logger logger = LoggerFactory.getLogger(GlobalStatus.class); + + private int authority_issuer_current_cpt_id = 1000; + + private int none_authority_issuer_current_cpt_id = 2000000; + + private int authority_issuer_current_policy_id = 1000; + + private int none_authority_issuer_current_policy_id = 2000000; + + private int presentationId = 1; + + //TODO:给文件加锁 + public static void storeStatusToFile(GlobalStatus globalStatus, String fileName) { + try { + ObjectMapper mapper = new ObjectMapper(); + File file = new File(fileName); + // if file does not exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + mapper.writeValue(file, globalStatus); + } catch (IOException e) { + logger.error("writer file exception", e); + } + } + + public static GlobalStatus readStatusFromFile(String fileName) { + try { + ObjectMapper mapper = new ObjectMapper(); + File file = new File(fileName); + // if file does not exists, then create it + if (file.exists()) { + return mapper.readValue(file, GlobalStatus.class); + } + file.createNewFile(); + return new GlobalStatus(); + } catch (IOException e) { + logger.error("writer file exception", e); + } + logger.error("readStatusFromFile() the {} does not exists.", fileName); + return null; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/HashString.java b/src/main/java/com/webank/weid/protocol/base/HashString.java new file mode 100644 index 00000000..6b33a76f --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/HashString.java @@ -0,0 +1,42 @@ + + +package com.webank.weid.protocol.base; + +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.protocol.inf.Hashable; + +/** + * The base data structure to represent a Hash value. + * + * @author chaoxinhu 2019.9 + */ +public class HashString implements Hashable { + + private String hash = StringUtils.EMPTY; + + public HashString(String hash) { + setHash(hash); + } + + @Override + public String getHash() { + return hash; + } + + /** + * Set hash value with a validity check. + * + * @param hash hash value + */ + public void setHash(String hash) { + if (StringUtils.isEmpty(hash) + || !Pattern.compile(WeIdConstant.HASH_VALUE_PATTERN).matcher(hash).matches()) { + return; + } + this.hash = hash; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/IssuerType.java b/src/main/java/com/webank/weid/protocol/base/IssuerType.java new file mode 100644 index 00000000..639c708c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/IssuerType.java @@ -0,0 +1,35 @@ + +package com.webank.weid.protocol.base; + +import lombok.Data; + +@Data +public class IssuerType { + /** + * Required: The Issuer Type Name. + */ + private String typeName; + + /** + * Required: The The Issuer Type Owner.. + */ + private String owner; + + /** + * Required: The create date of the Authority Issuer, in timestamp (Long) format. + */ + private Long created; + + /** + * transfer the IssuerType from weid-blockchain. + * @param type the IssuerType class in weid-blockchain + * @return WeIdDocument + */ + public static IssuerType fromBlockChain(com.webank.weid.blockchain.protocol.base.IssuerType type) { + IssuerType issuerType = new IssuerType(); + issuerType.setTypeName(type.getTypeName()); + issuerType.setCreated(type.getCreated()); + issuerType.setOwner(type.getOwner()); + return issuerType; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/PolicyAndChallenge.java b/src/main/java/com/webank/weid/protocol/base/PolicyAndChallenge.java new file mode 100644 index 00000000..2fe3c8d3 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/PolicyAndChallenge.java @@ -0,0 +1,26 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Getter; +import lombok.Setter; + +import com.webank.weid.protocol.inf.JsonSerializer; + +/** + * Created by Junqi Zhang on 2019/4/10. + */ +@Setter +@Getter +public class PolicyAndChallenge implements JsonSerializer { + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = -7730049255207201464L; + + private PresentationPolicyE presentationPolicyE; + + private Challenge challenge; +} + diff --git a/src/main/java/com/webank/weid/protocol/base/PolicyAndPreCredential.java b/src/main/java/com/webank/weid/protocol/base/PolicyAndPreCredential.java new file mode 100644 index 00000000..5c9ea950 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/PolicyAndPreCredential.java @@ -0,0 +1,40 @@ + + +package com.webank.weid.protocol.base; + +import java.util.Map; + +import lombok.Getter; +import lombok.Setter; + +import com.webank.weid.protocol.inf.JsonSerializer; + +/** + * policy and pre-credential. + * + * @author tonychen 2019年12月3日 + */ +@Getter +@Setter +public class PolicyAndPreCredential implements JsonSerializer { + + /** + * serial Version UID. + */ + private static final long serialVersionUID = -5224072665022845706L; + + /** + * policy and challenge. + */ + private PolicyAndChallenge policyAndChallenge; + + /** + * credential based on CPT 110. + */ + private CredentialPojo preCredential; + + /** + * extra data. + */ + private Map extra; +} diff --git a/src/main/java/com/webank/weid/protocol/base/PresentationE.java b/src/main/java/com/webank/weid/protocol/base/PresentationE.java new file mode 100644 index 00000000..049459b5 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/PresentationE.java @@ -0,0 +1,201 @@ + + +package com.webank.weid.protocol.base; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.protocol.inf.IProof; +import com.webank.weid.protocol.inf.RawSerializer; +import com.webank.weid.util.CredentialPojoUtils; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Created by Junqi Zhang on 2019/4/4. + */ +@Data +@EqualsAndHashCode +public class PresentationE implements RawSerializer, IProof { + + private static final Logger logger = LoggerFactory.getLogger(PresentationE.class); + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = -595605743843891841L; + + /** + * Required: The context field. + */ + private List context = new ArrayList(); + + private List type = new ArrayList(); + + private List verifiableCredential; + + private Map proof; + + /** + * 获取公钥Id,用于验证的时候识别publicKey. + * @return publicKeyId + */ + public String getVerificationMethod() { + return toString(getValueFromProof(proof, ParamKeyConstant.PROOF_VERIFICATION_METHOD_ID)); + } + + /** + * 获取challenge随机值. + * @return 返回challenge随机值. + */ + public String getNonce() { + return toString(getValueFromProof(proof, ParamKeyConstant.PROOF_NONCE)); + } + + /** + * 获取签名值Signature. + * @return 返回签名字符串Signature. + */ + public String getSignature() { + return toString(getValueFromProof(proof, ParamKeyConstant.PROOF_SIGNATURE)); + } + + /** + * 向proof中添加key-value. + * @param key proof中的 key + * @param value proof中key的value + */ + public void putProofValue(String key, Object value) { + if (proof == null) { + proof = new HashMap<>(); + } + proof.put(key, value); + } + + /** + * convert PresentationE to JSON String. + * @return PresentationE + */ + @Override + public String toJson() { + String json = DataToolUtils.convertTimestampToUtc(DataToolUtils.serialize(this)); + return DataToolUtils.addTagFromToJson(json); + } + + /** + * create PresentationE with JSON String. + * @param presentationJson the presentation JSON String + * @return PresentationE PresentationE + */ + public static PresentationE fromJson(String presentationJson) { + if (StringUtils.isBlank(presentationJson)) { + logger.error("create PresentationE with JSON String failed, " + + "the presentation JSON String is null"); + throw new DataTypeCastException("the presentation JSON String is null"); + } + String presentationString = presentationJson; + if (DataToolUtils.isValidFromToJson(presentationJson)) { + presentationString = DataToolUtils.removeTagFromToJson(presentationJson); + } + PresentationE presentationE = DataToolUtils.deserialize( + DataToolUtils.convertUtcToTimestamp(presentationString), + PresentationE.class); + if (presentationE == null + || presentationE.getVerifiableCredential() == null + || presentationE.getVerifiableCredential().isEmpty()) { + logger.error("create PresentationE with JSON String failed, " + + "due to convert UTC to Timestamp error"); + throw new DataTypeCastException("convert UTC to Timestamp error"); + } + for (CredentialPojo credentialPojo : presentationE.getVerifiableCredential()) { + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + logger.error("create PresentationE with JSON String failed, {}", + checkResp.getCodeDesc()); + throw new DataTypeCastException(checkResp.getCodeDesc()); + } + if (!CredentialPojoUtils.validClaimAndSaltForMap( + credentialPojo.getClaim(), + credentialPojo.getSalt())) { + logger.error("create PresentationE with JSON String failed, claim and salt of " + + "credentialPojo not match."); + throw new DataTypeCastException("claim and salt of credentialPojo not match."); + } + } + return presentationE; + } + + /** + * push the CredentialPojo into PresentationE. + * @param credentialPojo the credential + * @return true is success, others fail + */ + public boolean push(CredentialPojo credentialPojo) { + if (verifiableCredential == null || credentialPojo == null) { + logger.error("[push] the credentialPojo is null."); + return false; + } + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + logger.error("[push] the credentialPojo is invalid."); + return false; + } + verifiableCredential.add(credentialPojo); + logger.info("[push] the credentialPojo is added."); + return true; + } + + /** + * commit the credential to sign. + * @param weIdAuthentication the authentication + * @return true is success, others fail + */ + public boolean commit(WeIdAuthentication weIdAuthentication) { + if (weIdAuthentication == null + || weIdAuthentication.getWeIdPrivateKey() == null + || weIdAuthentication.getWeId() == null) { + logger.error("[commit] the weIdAuthentication is null."); + return false; + } + if (!WeIdUtils.validatePrivateKeyWeIdMatches( + weIdAuthentication.getWeIdPrivateKey(), + weIdAuthentication.getWeId())) { + logger.error("[commit] the private key does not match the current weid."); + return false; + } + if (!weIdAuthentication.getAuthenticationMethodId().equals(this.getVerificationMethod())) { + logger.error("[commit] the public key id does not match the presentation."); + return false; + } + // 更新proof里面的签名 + /*String signature = + DataToolUtils.secp256k1Sign( + this.toRawData(), + new BigInteger(weIdAuthentication.getWeIdPrivateKey().getPrivateKey()) + );*/ + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(this.toRawData(), weIdAuthentication.getWeIdPrivateKey().getPrivateKey()) + ); + this.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + logger.info("[commit] commit credential with weIdAuthentication is success."); + return true; + } + + @Override + public String toRawData() { + PresentationE presentation = DataToolUtils.clone(this); + presentation.proof = null; + return DataToolUtils.serialize(presentation); + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/PresentationPolicyE.java b/src/main/java/com/webank/weid/protocol/base/PresentationPolicyE.java new file mode 100644 index 00000000..4c5a77c2 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/PresentationPolicyE.java @@ -0,0 +1,177 @@ + + +package com.webank.weid.protocol.base; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.protocol.inf.JsonSerializer; +import com.webank.weid.util.DataToolUtils; + +/** + * The base data structure to handle Credential info. + * + * @author junqizhang 2019.04 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PresentationPolicyE extends Version implements JsonSerializer { + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = 3607089314849566766L; + + private static final Logger logger = LoggerFactory.getLogger(PresentationPolicyE.class); + + /** + * Policy ID. + */ + private Integer id; + + /** + * represent who publish this presentation policy. + */ + private String orgId; + + /** + * represent who publish this presentation policy. + */ + private String policyPublisherWeId; + + /** + * specify which properties in which credential are needed. + */ + private Map policy; + + /** + * extra data which policy presenter can use it store some specific business data. + */ + private Map extra; + + /** + * 新增字段,标识是支持零知识证明的policy还是原来的. + */ + private String policyType = "original"; + + /** + * create the PresentationPolicyE with policyFileName, + * please make sure the JSON file in your classPath. + * + * @param policyFileName the policyFileName + * @return the PresentationPolicyE + */ + public static PresentationPolicyE create(String policyFileName) { + PresentationPolicyE policy = null; + try { + JsonNode jsonNode = null; + //获取policyJson文件 转换成JsonNode + File file = new File(policyFileName); + logger.info("create policy file path:{}|{}", file.getAbsolutePath(), policyFileName); + if (file.exists()) { + jsonNode = DataToolUtils.loadJsonObjectFromFile(file); + } else { + // 去除了 / 开头 ("/" + policyFileName) + jsonNode = DataToolUtils.loadJsonObjectFromResource(policyFileName); + } + + if (jsonNode == null) { + logger.error("can not find the {} file in your classpath.", policyFileName); + return policy; + } + policy = fromJson(jsonNode.toString()); + } catch (IOException e) { + logger.error("create PresentationPolicyE has error, please check the log.", e); + } + return policy; + } + + /** + * create the PresentationPolicyE with JSON String. + * + * @param json the JSON String + * @return the PresentationPolicyE + */ + public static PresentationPolicyE fromJson(String json) { + PresentationPolicyE policy = null; + try { + //将Json转换成Map + HashMap policyMap = + DataToolUtils.deserialize(json, HashMap.class); + //获取policyJson中的policy 转换成Map + HashMap claimMap = + (HashMap)policyMap.get(CredentialConstant.CLAIM_POLICY_FIELD); + //遍历claimMap + Iterator it = claimMap.keySet().iterator(); + while (it.hasNext()) { + //得到每一个claim + HashMap claim = (HashMap)claimMap.get(it.next()); + //得到fieldsToBeDisclosed转换成Map + HashMap disclosedMap = + (HashMap)claim.get( + CredentialConstant.CLAIM_POLICY_DISCLOSED_FIELD + ); + //覆盖原来的fieldsToBeDisclosed为字符串 + claim.put( + CredentialConstant.CLAIM_POLICY_DISCLOSED_FIELD, + DataToolUtils.serialize(disclosedMap) + ); + } + //重新序列化为policyJson + String value = DataToolUtils.serialize(policyMap); + //反序列化policyJson为PresentationPolicyE + return DataToolUtils.deserialize(value, PresentationPolicyE.class); + } catch (Exception e) { + logger.error("create PresentationPolicyE has error, please check the log.", e); + } + return policy; + } + + @Override + public String toJson() { + String jsonString = DataToolUtils.serialize(this); + HashMap policyEMap = DataToolUtils.deserialize(jsonString, HashMap.class); + Map policy1 = + (HashMap)policyEMap.get(CredentialConstant.CLAIM_POLICY_FIELD); + for (Map.Entry entry : policy1.entrySet()) { + HashMap claimPolicyMap = (HashMap)entry.getValue(); + HashMap disclosureMap = + DataToolUtils.deserialize( + (String)claimPolicyMap.get(CredentialConstant.CLAIM_POLICY_DISCLOSED_FIELD), + HashMap.class + ); + claimPolicyMap.put(CredentialConstant.CLAIM_POLICY_DISCLOSED_FIELD, disclosureMap); + } + return DataToolUtils.serialize(policyEMap); + } + + /** + * transfer PresentationPolicyE class from weid-blockchain. + * @param presentation the PresentationPolicyE object in weid-blockchain + * @return PresentationPolicyE + */ + public static PresentationPolicyE fromBlockChain(com.webank.weid.blockchain.protocol.base.PresentationPolicyE presentation) { + PresentationPolicyE presentationPolicyE = new PresentationPolicyE(); + presentationPolicyE.setId(presentation.getId()); + presentationPolicyE.setOrgId(presentation.getOrgId()); + presentationPolicyE.setPolicyPublisherWeId(presentation.getPolicyPublisherWeId()); + presentationPolicyE.setExtra(presentation.getExtra()); + presentationPolicyE.setPolicyType(presentation.getPolicyType()); + Map policyMap = new HashMap<>(); + for(Map.Entry entry : presentation.getPolicy().entrySet()){ + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed(entry.getValue()); + policyMap.put(entry.getKey(), claimPolicy); + } + presentationPolicyE.setPolicy(policyMap); + return presentationPolicyE; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/PublicKeyProperty.java b/src/main/java/com/webank/weid/protocol/base/PublicKeyProperty.java deleted file mode 100644 index a171d071..00000000 --- a/src/main/java/com/webank/weid/protocol/base/PublicKeyProperty.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.protocol.base; - -import lombok.Data; - -/** - * The base data structure for public key properties. - * - * @author tonychen 2018.10.8 - */ -@Data -public class PublicKeyProperty { - - /** - * Required: The id. - */ - private String id; - - /** - * Required: The type. - */ - private String type = "Secp256k1VerificationKey2018"; - - /** - * Required: The owner. - */ - private String owner; - - /** - * Required: The public key. - */ - private String publicKey; -} diff --git a/src/main/java/com/webank/weid/protocol/base/ServiceProperty.java b/src/main/java/com/webank/weid/protocol/base/ServiceProperty.java index dc2ce944..2e8b4c04 100644 --- a/src/main/java/com/webank/weid/protocol/base/ServiceProperty.java +++ b/src/main/java/com/webank/weid/protocol/base/ServiceProperty.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; @@ -29,6 +12,11 @@ @Data public class ServiceProperty { + /** + * Required: The id. + */ + private String id; + /** * Required: The type. */ @@ -38,4 +26,31 @@ public class ServiceProperty { * Required: The service endpoint. */ private String serviceEndpoint; + + public String toString() { + return this.id + ',' + this.type + ',' + this.serviceEndpoint; + } + + public static ServiceProperty fromString(String serviceString) { + String[] result = serviceString.split(","); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setId(result[0]); + serviceProperty.setType(result[1]); + serviceProperty.setServiceEndpoint(result[2]); + return serviceProperty; + } + public static ServiceProperty fromBlockChain(com.webank.weid.blockchain.protocol.base.ServiceProperty service) { + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setId(service.getId()); + serviceProperty.setType(service.getType()); + serviceProperty.setServiceEndpoint(service.getServiceEndpoint()); + return serviceProperty; + } + public static com.webank.weid.blockchain.protocol.base.ServiceProperty toBlockChain(ServiceProperty service) { + com.webank.weid.blockchain.protocol.base.ServiceProperty serviceProperty = new com.webank.weid.blockchain.protocol.base.ServiceProperty(); + serviceProperty.setId(service.getId()); + serviceProperty.setType(service.getType()); + serviceProperty.setServiceEndpoint(service.getServiceEndpoint()); + return serviceProperty; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/Version.java b/src/main/java/com/webank/weid/protocol/base/Version.java new file mode 100644 index 00000000..691e67bc --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/Version.java @@ -0,0 +1,16 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Created by Junqi Zhang on 2019/4/10. + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class Version { + + private Integer version; +} diff --git a/src/main/java/com/webank/weid/protocol/base/WeIdAuthentication.java b/src/main/java/com/webank/weid/protocol/base/WeIdAuthentication.java new file mode 100644 index 00000000..1f9e5829 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/WeIdAuthentication.java @@ -0,0 +1,55 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Data; + +/** + * The base data structure to handle WeIdentity DID authority info. + * + * @author afeexian + */ +@Data +public class WeIdAuthentication { + + /** + * Required: The weIdentity DID. + */ + private String weId; + + /** + * the method Id. + */ + private String authenticationMethodId; + + /** + * Required: The private key or The weIdentity DID. + */ + private WeIdPrivateKey weIdPrivateKey; + + public WeIdAuthentication() { + super(); + } + + /** + * Constructor with weId and privateKey. + * @param weId the weId + * @param privateKey the privateKey + */ + public WeIdAuthentication(String weId, String privateKey) { + this.weId = weId; + this.weIdPrivateKey = new WeIdPrivateKey(); + this.weIdPrivateKey.setPrivateKey(privateKey); + } + + /** + * Constructor with weId, privateKey and weIdPublicKeyId. + * @param weId the weId + * @param privateKey the privateKey + * @param authenticationMethodId the weIdPublicKeyId + */ + public WeIdAuthentication(String weId, String privateKey, String authenticationMethodId) { + this(weId, privateKey); + this.authenticationMethodId = authenticationMethodId; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/WeIdDocument.java b/src/main/java/com/webank/weid/protocol/base/WeIdDocument.java index 84848294..6138dff8 100644 --- a/src/main/java/com/webank/weid/protocol/base/WeIdDocument.java +++ b/src/main/java/com/webank/weid/protocol/base/WeIdDocument.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; @@ -23,14 +6,30 @@ import java.util.List; import lombok.Data; +import lombok.EqualsAndHashCode; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.protocol.inf.JsonSerializer; +import com.webank.weid.util.DataToolUtils; /** * The base data structure to handle WeIdentity DID Document info. * - * @author tonychen 2018.9.29 + * @author afeexian 2022.8.29 */ @Data -public class WeIdDocument { +public class WeIdDocument implements JsonSerializer { + + private static final Logger logger = LoggerFactory.getLogger(WeIdDocument.class); + + /** + * the serialVersionUID. + */ + private static final long serialVersionUID = 411522771907189878L; /** * Required: The id. @@ -38,27 +37,81 @@ public class WeIdDocument { private String id; /** - * Required: The created. + * Required: The authentication list. */ - private Long created; + private List authentication = new ArrayList<>(); /** - * Required: The updated. + * Required: The service list. */ - private Long updated; - + private List service = new ArrayList<>(); + + @Override + public String toJson() { + return DataToolUtils.addTagFromToJson(DataToolUtils.serialize(this)); + } + /** - * Required: The public key list. + * create WeIdDocument with JSON String. + * @param weIdDocumentJson the weIdDocument JSON String + * @return WeIdDocument */ - private List publicKey = new ArrayList<>(); + public static WeIdDocument fromJson(String weIdDocumentJson) { + if (StringUtils.isBlank(weIdDocumentJson)) { + logger.error("create WeIdDocument with JSON String failed, " + + "the WeIdDocument JSON String is null"); + throw new DataTypeCastException("the WeIdDocument JSON String is null."); + } + String weIdDocumentString = weIdDocumentJson; + if (DataToolUtils.isValidFromToJson(weIdDocumentJson)) { + weIdDocumentString = DataToolUtils.removeTagFromToJson(weIdDocumentJson); + } + return DataToolUtils.deserialize(weIdDocumentString, WeIdDocument.class); + } /** - * Required: The authentication list. + * create WeIdDocument with document from weid-blockchain. + * @param document the weIdDocument JSON String + * @return WeIdDocument */ - private List authentication = new ArrayList<>(); + public static WeIdDocument fromBlockChain(com.webank.weid.blockchain.protocol.base.WeIdDocument document) { + WeIdDocument weIdDocument = new WeIdDocument(); + weIdDocument.setId(document.getId()); + List authenticationList = new ArrayList<>(); + for(com.webank.weid.blockchain.protocol.base.AuthenticationProperty authentication : document.getAuthentication()){ + AuthenticationProperty authenticationProperty = AuthenticationProperty.fromBlockChain(authentication); + authenticationList.add(authenticationProperty); + } + weIdDocument.setAuthentication(authenticationList); + List serviceList = new ArrayList<>(); + for(com.webank.weid.blockchain.protocol.base.ServiceProperty service : document.getService()){ + ServiceProperty serviceProperty = ServiceProperty.fromBlockChain(service); + serviceList.add(serviceProperty); + } + weIdDocument.setService(serviceList); + return weIdDocument; + } /** - * Required: The service list. + * change WeIdDocument to document for weid-blockchain. + * @param document the weIdDocument JSON String + * @return WeIdDocument */ - private List service = new ArrayList<>(); + public static com.webank.weid.blockchain.protocol.base.WeIdDocument toBlockChain(WeIdDocument document) { + com.webank.weid.blockchain.protocol.base.WeIdDocument weIdDocument = new com.webank.weid.blockchain.protocol.base.WeIdDocument(); + weIdDocument.setId(document.getId()); + List authenticationList = new ArrayList<>(); + for(AuthenticationProperty authentication : document.getAuthentication()){ + com.webank.weid.blockchain.protocol.base.AuthenticationProperty authenticationProperty = AuthenticationProperty.toBlockChain(authentication); + authenticationList.add(authenticationProperty); + } + weIdDocument.setAuthentication(authenticationList); + List serviceList = new ArrayList<>(); + for(ServiceProperty service : document.getService()){ + com.webank.weid.blockchain.protocol.base.ServiceProperty serviceProperty = ServiceProperty.toBlockChain(service); + serviceList.add(serviceProperty); + } + weIdDocument.setService(serviceList); + return weIdDocument; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/WeIdDocumentMetadata.java b/src/main/java/com/webank/weid/protocol/base/WeIdDocumentMetadata.java new file mode 100644 index 00000000..8da78aac --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/base/WeIdDocumentMetadata.java @@ -0,0 +1,38 @@ + + +package com.webank.weid.protocol.base; + +import lombok.Data; + +@Data +public class WeIdDocumentMetadata { + + /** + * Required: The created. + */ + private Long created; + + /** + * Required: The updated. + */ + private Long updated; + + /** + * Required: The deactivated. + */ + private boolean deactivated; + + /** + * Required: The versionId. + */ + private int versionId; + + public static WeIdDocumentMetadata fromBlockChain(com.webank.weid.blockchain.protocol.base.WeIdDocumentMetadata metadata) { + WeIdDocumentMetadata weIdDocumentMetadata = new WeIdDocumentMetadata(); + weIdDocumentMetadata.setCreated(metadata.getCreated()); + weIdDocumentMetadata.setUpdated(metadata.getUpdated()); + weIdDocumentMetadata.setDeactivated(metadata.isDeactivated()); + weIdDocumentMetadata.setVersionId(metadata.getVersionId()); + return weIdDocumentMetadata; + } +} diff --git a/src/main/java/com/webank/weid/protocol/base/WeIdPrivateKey.java b/src/main/java/com/webank/weid/protocol/base/WeIdPrivateKey.java index 810a546f..c79e918c 100644 --- a/src/main/java/com/webank/weid/protocol/base/WeIdPrivateKey.java +++ b/src/main/java/com/webank/weid/protocol/base/WeIdPrivateKey.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; @@ -33,4 +16,12 @@ public class WeIdPrivateKey { * Required: The private key. */ private String privateKey; + + public WeIdPrivateKey() { + super(); + } + + public WeIdPrivateKey(String privateKey) { + this.privateKey = privateKey; + } } diff --git a/src/main/java/com/webank/weid/protocol/base/WeIdPublicKey.java b/src/main/java/com/webank/weid/protocol/base/WeIdPublicKey.java index 7fb04bb0..cbca9694 100644 --- a/src/main/java/com/webank/weid/protocol/base/WeIdPublicKey.java +++ b/src/main/java/com/webank/weid/protocol/base/WeIdPublicKey.java @@ -1,21 +1,4 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.base; diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt101.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt101.java new file mode 100644 index 00000000..9d979d02 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt101.java @@ -0,0 +1,156 @@ +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Data Authorization Token + *

+ * Authorize data between WeIDs via the exposed Service Endpoint + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "duration", + "fromWeId", + "resourceId", + "serviceUrl", + "toWeId" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt101 { + + /** + * Authorize to this WeID + * (Required) + * + */ + @JsonProperty("duration") + @JsonPropertyDescription("Authorize to this WeID") + private Long duration; + /** + * Authorize from this WeID + * (Required) + * + */ + @JsonProperty("fromWeId") + @JsonPropertyDescription("Authorize from this WeID") + private String fromWeId; + /** + * Authorized Resource ID + * (Required) + * + */ + @JsonProperty("resourceId") + @JsonPropertyDescription("Authorized Resource ID") + private String resourceId; + /** + * Service Endpoint URL + * (Required) + * + */ + @JsonProperty("serviceUrl") + @JsonPropertyDescription("Service Endpoint URL") + private String serviceUrl; + /** + * Duration of Validity in seconds + * (Required) + * + */ + @JsonProperty("toWeId") + @JsonPropertyDescription("Duration of Validity in seconds") + private String toWeId; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt101 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("duration"); + sb.append('='); + sb.append(((this.duration == null)?"":this.duration)); + sb.append(','); + sb.append("fromWeId"); + sb.append('='); + sb.append(((this.fromWeId == null)?"":this.fromWeId)); + sb.append(','); + sb.append("resourceId"); + sb.append('='); + sb.append(((this.resourceId == null)?"":this.resourceId)); + sb.append(','); + sb.append("serviceUrl"); + sb.append('='); + sb.append(((this.serviceUrl == null)?"":this.serviceUrl)); + sb.append(','); + sb.append("toWeId"); + sb.append('='); + sb.append(((this.toWeId == null)?"":this.toWeId)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.duration == null)? 0 :this.duration.hashCode())); + result = ((result* 31)+((this.fromWeId == null)? 0 :this.fromWeId.hashCode())); + result = ((result* 31)+((this.resourceId == null)? 0 :this.resourceId.hashCode())); + result = ((result* 31)+((this.toWeId == null)? 0 :this.toWeId.hashCode())); + result = ((result* 31)+((this.serviceUrl == null)? 0 :this.serviceUrl.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt101) == false) { + return false; + } + Cpt101 rhs = ((Cpt101) other); + return (((((((this.duration == rhs.duration)||((this.duration!= null)&&this.duration.equals(rhs.duration)))&&((this.fromWeId == rhs.fromWeId)||((this.fromWeId!= null)&&this.fromWeId.equals(rhs.fromWeId))))&&((this.resourceId == rhs.resourceId)||((this.resourceId!= null)&&this.resourceId.equals(rhs.resourceId))))&&((this.toWeId == rhs.toWeId)||((this.toWeId!= null)&&this.toWeId.equals(rhs.toWeId))))&&((this.serviceUrl == rhs.serviceUrl)||((this.serviceUrl!= null)&&this.serviceUrl.equals(rhs.serviceUrl))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt102.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt102.java new file mode 100644 index 00000000..c4e44270 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt102.java @@ -0,0 +1,70 @@ + +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt102 { + + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt102 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt102) == false) { + return false; + } + Cpt102 rhs = ((Cpt102) other); + return ((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt103.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt103.java new file mode 100644 index 00000000..36f4bea8 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt103.java @@ -0,0 +1,121 @@ +package com.webank.weid.protocol.cpt; + +import com.webank.weid.protocol.base.Challenge; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "challenge", + "id", + "proof" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt103 { + + /** + * The challenge + * (Required) + * + */ + @JsonProperty("challenge") + @JsonPropertyDescription("The challenge") + private Challenge challenge; + /** + * The entity's weidentity did + * (Required) + * + */ + @JsonProperty("id") + @JsonPropertyDescription("The entity's weidentity did") + private String id; + /** + * The proof + * (Required) + * + */ + @JsonProperty("proof") + @JsonPropertyDescription("The proof") + private String proof; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt103 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("challenge"); + sb.append('='); + sb.append(((this.challenge == null)?"":this.challenge)); + sb.append(','); + sb.append("id"); + sb.append('='); + sb.append(((this.id == null)?"":this.id)); + sb.append(','); + sb.append("proof"); + sb.append('='); + sb.append(((this.proof == null)?"":this.proof)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.challenge == null)? 0 :this.challenge.hashCode())); + result = ((result* 31)+((this.id == null)? 0 :this.id.hashCode())); + result = ((result* 31)+((this.proof == null)? 0 :this.proof.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt103) == false) { + return false; + } + Cpt103 rhs = ((Cpt103) other); + return (((((this.challenge == rhs.challenge)||((this.challenge!= null)&&this.challenge.equals(rhs.challenge)))&&((this.id == rhs.id)||((this.id!= null)&&this.id.equals(rhs.id))))&&((this.proof == rhs.proof)||((this.proof!= null)&&this.proof.equals(rhs.proof))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt104.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt104.java new file mode 100644 index 00000000..76423368 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt104.java @@ -0,0 +1,70 @@ + +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt104 { + + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt104 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt104) == false) { + return false; + } + Cpt104 rhs = ((Cpt104) other); + return ((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt105.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt105.java new file mode 100644 index 00000000..ff49e803 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt105.java @@ -0,0 +1,169 @@ +package com.webank.weid.protocol.cpt; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * API Endpoint + *

+ * API Endpoint address disclosure + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "argType", + "description", + "endpointName", + "hostport", + "id", + "version" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt105 { + + /** + * Argument types in sequence + * (Required) + * + */ + @JsonProperty("argType") + @JsonPropertyDescription("Argument types in sequence") + private List argType = new ArrayList(); + /** + * + * (Required) + * + */ + @JsonProperty("description") + private String description; + /** + * + * (Required) + * + */ + @JsonProperty("endpointName") + private String endpointName; + /** + * Network host and port + * (Required) + * + */ + @JsonProperty("hostport") + @JsonPropertyDescription("Network host and port") + private String hostport; + /** + * Owner WeIdentity DID + * (Required) + * + */ + @JsonProperty("id") + @JsonPropertyDescription("Owner WeIdentity DID") + private String id; + /** + * API Version + * (Required) + * + */ + @JsonProperty("version") + @JsonPropertyDescription("API Version") + private String version; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt105 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("argType"); + sb.append('='); + sb.append(((this.argType == null)?"":this.argType)); + sb.append(','); + sb.append("description"); + sb.append('='); + sb.append(((this.description == null)?"":this.description)); + sb.append(','); + sb.append("endpointName"); + sb.append('='); + sb.append(((this.endpointName == null)?"":this.endpointName)); + sb.append(','); + sb.append("hostport"); + sb.append('='); + sb.append(((this.hostport == null)?"":this.hostport)); + sb.append(','); + sb.append("id"); + sb.append('='); + sb.append(((this.id == null)?"":this.id)); + sb.append(','); + sb.append("version"); + sb.append('='); + sb.append(((this.version == null)?"":this.version)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.argType == null)? 0 :this.argType.hashCode())); + result = ((result* 31)+((this.description == null)? 0 :this.description.hashCode())); + result = ((result* 31)+((this.endpointName == null)? 0 :this.endpointName.hashCode())); + result = ((result* 31)+((this.hostport == null)? 0 :this.hostport.hashCode())); + result = ((result* 31)+((this.id == null)? 0 :this.id.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.version == null)? 0 :this.version.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt105) == false) { + return false; + } + Cpt105 rhs = ((Cpt105) other); + return ((((((((this.argType == rhs.argType)||((this.argType!= null)&&this.argType.equals(rhs.argType)))&&((this.description == rhs.description)||((this.description!= null)&&this.description.equals(rhs.description))))&&((this.endpointName == rhs.endpointName)||((this.endpointName!= null)&&this.endpointName.equals(rhs.endpointName))))&&((this.hostport == rhs.hostport)||((this.hostport!= null)&&this.hostport.equals(rhs.hostport))))&&((this.id == rhs.id)||((this.id!= null)&&this.id.equals(rhs.id))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.version == rhs.version)||((this.version!= null)&&this.version.equals(rhs.version)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt106.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt106.java new file mode 100644 index 00000000..51519d09 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt106.java @@ -0,0 +1,103 @@ +package com.webank.weid.protocol.cpt; + +import com.webank.weid.protocol.base.Credential; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Embedded Signature + *

+ * Embedded Signature object for multi-sign + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "credentialList" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt106 { + + /** + * Original credential list to be signed + * (Required) + * + */ + @JsonProperty("credentialList") + @JsonPropertyDescription("Original credential list to be signed") + private List credentialList = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt106 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("credentialList"); + sb.append('='); + sb.append(((this.credentialList == null)?"":this.credentialList)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.credentialList == null)? 0 :this.credentialList.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt106) == false) { + return false; + } + Cpt106 rhs = ((Cpt106) other); + return (((this.credentialList == rhs.credentialList)||((this.credentialList!= null)&&this.credentialList.equals(rhs.credentialList)))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt107.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt107.java new file mode 100644 index 00000000..5486136d --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt107.java @@ -0,0 +1,100 @@ +package com.webank.weid.protocol.cpt; + +import com.webank.weid.protocol.base.CredentialPojo; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Embedded Signature + *

+ * Embedded Signature object for multi-sign + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "credentialList" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt107 { + + /** + * + * (Required) + * + */ + @JsonProperty("credentialList") + private List credentialList = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt107 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("credentialList"); + sb.append('='); + sb.append(((this.credentialList == null)?"":this.credentialList)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.credentialList == null)? 0 :this.credentialList.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt107) == false) { + return false; + } + Cpt107 rhs = ((Cpt107) other); + return (((this.credentialList == rhs.credentialList)||((this.credentialList!= null)&&this.credentialList.equals(rhs.credentialList)))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt108.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt108.java new file mode 100644 index 00000000..46f6e953 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt108.java @@ -0,0 +1,159 @@ +package com.webank.weid.protocol.cpt; + +import com.webank.weid.protocol.base.CredentialPojo; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Trusted timestamping + *

+ * Trusted timestamping envelope + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "authoritySignature", + "claimHash", + "credentialList", + "timestamp", + "timestampAuthority" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt108 { + + /** + * Signature value from Authority, signed by Timestamp authority. authoritySignature = sign( hashKey ) + * (Required) + * + */ + @JsonProperty("authoritySignature") + @JsonPropertyDescription("Signature value from Authority, signed by Timestamp authority. authoritySignature = sign( hashKey )") + private String authoritySignature; + /** + * calculate the hash from the credentials. + * (Required) + * + */ + @JsonProperty("claimHash") + @JsonPropertyDescription("calculate the hash from the credentials.") + private String claimHash; + /** + * Original credential list to be signed + * (Required) + * + */ + @JsonProperty("credentialList") + @JsonPropertyDescription("Original credential list to be signed") + private List credentialList = new ArrayList(); + /** + * trusted timestamping provided by the trusted third party or by the consensus of each node in the consortium chain + * (Required) + * + */ + @JsonProperty("timestamp") + @JsonPropertyDescription("trusted timestamping provided by the trusted third party or by the consensus of each node in the consortium chain") + private Integer timestamp; + /** + * information about timestamp authority + * (Required) + * + */ + @JsonProperty("timestampAuthority") + @JsonPropertyDescription("information about timestamp authority") + private String timestampAuthority; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt108 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("authoritySignature"); + sb.append('='); + sb.append(((this.authoritySignature == null)?"":this.authoritySignature)); + sb.append(','); + sb.append("claimHash"); + sb.append('='); + sb.append(((this.claimHash == null)?"":this.claimHash)); + sb.append(','); + sb.append("credentialList"); + sb.append('='); + sb.append(((this.credentialList == null)?"":this.credentialList)); + sb.append(','); + sb.append("timestamp"); + sb.append('='); + sb.append(((this.timestamp == null)?"":this.timestamp)); + sb.append(','); + sb.append("timestampAuthority"); + sb.append('='); + sb.append(((this.timestampAuthority == null)?"":this.timestampAuthority)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.timestampAuthority == null)? 0 :this.timestampAuthority.hashCode())); + result = ((result* 31)+((this.authoritySignature == null)? 0 :this.authoritySignature.hashCode())); + result = ((result* 31)+((this.claimHash == null)? 0 :this.claimHash.hashCode())); + result = ((result* 31)+((this.credentialList == null)? 0 :this.credentialList.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.timestamp == null)? 0 :this.timestamp.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt108) == false) { + return false; + } + Cpt108 rhs = ((Cpt108) other); + return (((((((this.timestampAuthority == rhs.timestampAuthority)||((this.timestampAuthority!= null)&&this.timestampAuthority.equals(rhs.timestampAuthority)))&&((this.authoritySignature == rhs.authoritySignature)||((this.authoritySignature!= null)&&this.authoritySignature.equals(rhs.authoritySignature))))&&((this.claimHash == rhs.claimHash)||((this.claimHash!= null)&&this.claimHash.equals(rhs.claimHash))))&&((this.credentialList == rhs.credentialList)||((this.credentialList!= null)&&this.credentialList.equals(rhs.credentialList))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.timestamp == rhs.timestamp)||((this.timestamp!= null)&&this.timestamp.equals(rhs.timestamp)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt109.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt109.java new file mode 100644 index 00000000..0fa4164c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt109.java @@ -0,0 +1,142 @@ +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Trusted Timestamp + *

+ * Trusted Timestamp from authorized 3rd-party, or chain consensus + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "claimHash", + "hashKey", + "signatureList", + "timestamp" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt109 { + + /** + * calculate the hash from the entire list rather than from any single credential + * (Required) + * + */ + @JsonProperty("claimHash") + @JsonPropertyDescription("calculate the hash from the entire list rather than from any single credential") + private String claimHash; + /** + * hashKey = hash(claimHash + timestamp) hashKey will be the key in the smart contract + * (Required) + * + */ + @JsonProperty("hashKey") + @JsonPropertyDescription("hashKey = hash(claimHash + timestamp) hashKey will be the key in the smart contract") + private String hashKey; + /** + * signed by Timestamp authority signature = sign( hashKey ) + * (Required) + * + */ + @JsonProperty("signatureList") + @JsonPropertyDescription("signed by Timestamp authority signature = sign( hashKey )") + private String signatureList; + /** + * trusted timestamp provided by the trusted third party or by the consensus of each node in the consortium chain + * (Required) + * + */ + @JsonProperty("timestamp") + @JsonPropertyDescription("trusted timestamp provided by the trusted third party or by the consensus of each node in the consortium chain") + private Integer timestamp; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt109 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("claimHash"); + sb.append('='); + sb.append(((this.claimHash == null)?"":this.claimHash)); + sb.append(','); + sb.append("hashKey"); + sb.append('='); + sb.append(((this.hashKey == null)?"":this.hashKey)); + sb.append(','); + sb.append("signatureList"); + sb.append('='); + sb.append(((this.signatureList == null)?"":this.signatureList)); + sb.append(','); + sb.append("timestamp"); + sb.append('='); + sb.append(((this.timestamp == null)?"":this.timestamp)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.signatureList == null)? 0 :this.signatureList.hashCode())); + result = ((result* 31)+((this.hashKey == null)? 0 :this.hashKey.hashCode())); + result = ((result* 31)+((this.claimHash == null)? 0 :this.claimHash.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.timestamp == null)? 0 :this.timestamp.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt109) == false) { + return false; + } + Cpt109 rhs = ((Cpt109) other); + return ((((((this.signatureList == rhs.signatureList)||((this.signatureList!= null)&&this.signatureList.equals(rhs.signatureList)))&&((this.hashKey == rhs.hashKey)||((this.hashKey!= null)&&this.hashKey.equals(rhs.hashKey))))&&((this.claimHash == rhs.claimHash)||((this.claimHash!= null)&&this.claimHash.equals(rhs.claimHash))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.timestamp == rhs.timestamp)||((this.timestamp!= null)&&this.timestamp.equals(rhs.timestamp)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt11.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt11.java new file mode 100644 index 00000000..c7acda6b --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt11.java @@ -0,0 +1,154 @@ +package com.webank.weid.protocol.cpt; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * test cpt + *

+ * Reserved CPT 11 + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "cptId", + "gender", + "tags", + "userId", + "userName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt11 { + + /** + * + * (Required) + * + */ + @JsonProperty("cptId") + private Integer cptId; + /** + * + * (Required) + * + */ + @JsonProperty("gender") + private String gender; + /** + * Registered Tags + * (Required) + * + */ + @JsonProperty("tags") + @JsonPropertyDescription("Registered Tags") + private List tags = new ArrayList(); + /** + * + * (Required) + * + */ + @JsonProperty("userId") + private String userId; + /** + * + * (Required) + * + */ + @JsonProperty("userName") + private String userName; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt11 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("cptId"); + sb.append('='); + sb.append(((this.cptId == null)?"":this.cptId)); + sb.append(','); + sb.append("gender"); + sb.append('='); + sb.append(((this.gender == null)?"":this.gender)); + sb.append(','); + sb.append("tags"); + sb.append('='); + sb.append(((this.tags == null)?"":this.tags)); + sb.append(','); + sb.append("userId"); + sb.append('='); + sb.append(((this.userId == null)?"":this.userId)); + sb.append(','); + sb.append("userName"); + sb.append('='); + sb.append(((this.userName == null)?"":this.userName)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.gender == null)? 0 :this.gender.hashCode())); + result = ((result* 31)+((this.cptId == null)? 0 :this.cptId.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.userName == null)? 0 :this.userName.hashCode())); + result = ((result* 31)+((this.userId == null)? 0 :this.userId.hashCode())); + result = ((result* 31)+((this.tags == null)? 0 :this.tags.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt11) == false) { + return false; + } + Cpt11 rhs = ((Cpt11) other); + return (((((((this.gender == rhs.gender)||((this.gender!= null)&&this.gender.equals(rhs.gender)))&&((this.cptId == rhs.cptId)||((this.cptId!= null)&&this.cptId.equals(rhs.cptId))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.userName == rhs.userName)||((this.userName!= null)&&this.userName.equals(rhs.userName))))&&((this.userId == rhs.userId)||((this.userId!= null)&&this.userId.equals(rhs.userId))))&&((this.tags == rhs.tags)||((this.tags!= null)&&this.tags.equals(rhs.tags)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt110.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt110.java new file mode 100644 index 00000000..9404d517 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt110.java @@ -0,0 +1,163 @@ +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + + +/** + * Metadata CPT + *

+ * User request issuer to sign credential + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "context", + "cptId", + "credentialId", + "expirationDate", + "issuanceDate", + "issuer" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt110 { + + /** + * + * (Required) + * + */ + @JsonProperty("context") + private String context; + /** + * + * (Required) + * + */ + @JsonProperty("cptId") + private Integer cptId; + /** + * + * (Required) + * + */ + @JsonProperty("credentialId") + private String credentialId; + /** + * + * (Required) + * + */ + @JsonProperty("expirationDate") + private Integer expirationDate; + /** + * + * (Required) + * + */ + @JsonProperty("issuanceDate") + private Integer issuanceDate; + /** + * + * (Required) + * + */ + @JsonProperty("issuer") + private String issuer; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt110 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("context"); + sb.append('='); + sb.append(((this.context == null)?"":this.context)); + sb.append(','); + sb.append("cptId"); + sb.append('='); + sb.append(((this.cptId == null)?"":this.cptId)); + sb.append(','); + sb.append("credentialId"); + sb.append('='); + sb.append(((this.credentialId == null)?"":this.credentialId)); + sb.append(','); + sb.append("expirationDate"); + sb.append('='); + sb.append(((this.expirationDate == null)?"":this.expirationDate)); + sb.append(','); + sb.append("issuanceDate"); + sb.append('='); + sb.append(((this.issuanceDate == null)?"":this.issuanceDate)); + sb.append(','); + sb.append("issuer"); + sb.append('='); + sb.append(((this.issuer == null)?"":this.issuer)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.cptId == null)? 0 :this.cptId.hashCode())); + result = ((result* 31)+((this.issuanceDate == null)? 0 :this.issuanceDate.hashCode())); + result = ((result* 31)+((this.context == null)? 0 :this.context.hashCode())); + result = ((result* 31)+((this.credentialId == null)? 0 :this.credentialId.hashCode())); + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.issuer == null)? 0 :this.issuer.hashCode())); + result = ((result* 31)+((this.expirationDate == null)? 0 :this.expirationDate.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt110) == false) { + return false; + } + Cpt110 rhs = ((Cpt110) other); + return ((((((((this.cptId == rhs.cptId)||((this.cptId!= null)&&this.cptId.equals(rhs.cptId)))&&((this.issuanceDate == rhs.issuanceDate)||((this.issuanceDate!= null)&&this.issuanceDate.equals(rhs.issuanceDate))))&&((this.context == rhs.context)||((this.context!= null)&&this.context.equals(rhs.context))))&&((this.credentialId == rhs.credentialId)||((this.credentialId!= null)&&this.credentialId.equals(rhs.credentialId))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.issuer == rhs.issuer)||((this.issuer!= null)&&this.issuer.equals(rhs.issuer))))&&((this.expirationDate == rhs.expirationDate)||((this.expirationDate!= null)&&this.expirationDate.equals(rhs.expirationDate)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt111.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt111.java new file mode 100644 index 00000000..e7602d59 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt111.java @@ -0,0 +1,126 @@ +package com.webank.weid.protocol.cpt; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import lombok.Data; + + +/** + * User CPT + *

+ * User request issuer to sign credential + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "cptId", + "credentialSignatureRequest", + "userNonce" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt111 { + + /** + * + * (Required) + * + */ + @JsonProperty("cptId") + private String cptId; + /** + * credential Signature Request + * (Required) + * + */ + @JsonProperty("credentialSignatureRequest") + @JsonPropertyDescription("credential Signature Request") + private String credentialSignatureRequest; + /** + * + * (Required) + * + */ + @JsonProperty("userNonce") + private String userNonce; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt111 .class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("cptId"); + sb.append('='); + sb.append(((this.cptId == null)?"":this.cptId)); + sb.append(','); + sb.append("credentialSignatureRequest"); + sb.append('='); + sb.append(((this.credentialSignatureRequest == null)?"":this.credentialSignatureRequest)); + sb.append(','); + sb.append("userNonce"); + sb.append('='); + sb.append(((this.userNonce == null)?"":this.userNonce)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.cptId == null)? 0 :this.cptId.hashCode())); + result = ((result* 31)+((this.credentialSignatureRequest == null)? 0 :this.credentialSignatureRequest.hashCode())); + result = ((result* 31)+((this.userNonce == null)? 0 :this.userNonce.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt111) == false) { + return false; + } + Cpt111 rhs = ((Cpt111) other); + return (((((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))&&((this.cptId == rhs.cptId)||((this.cptId!= null)&&this.cptId.equals(rhs.cptId))))&&((this.credentialSignatureRequest == rhs.credentialSignatureRequest)||((this.credentialSignatureRequest!= null)&&this.credentialSignatureRequest.equals(rhs.credentialSignatureRequest))))&&((this.userNonce == rhs.userNonce)||((this.userNonce!= null)&&this.userNonce.equals(rhs.userNonce)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt112.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt112.java new file mode 100644 index 00000000..ba1aa46c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt112.java @@ -0,0 +1,69 @@ +package com.webank.weid.protocol.cpt; + +import javax.annotation.Generated; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import lombok.Data; + +/** + * Metadata CPT + *

+ * User request issuer to sign credential + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "major", + "issuanceDate", + "name", + "gender", + "birthDate", + "issuerName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt112 { + /* + * Certicate atrribute + */ + + @JsonProperty("id") + @JsonPropertyDescription("Id of this diploma") + private String id; + + @JsonProperty("major") + @JsonPropertyDescription("Major of this diploma") + private String major; + + @JsonProperty("issuanceDate") + @JsonPropertyDescription("IssuanceDate of this diploma") + private Long issuanceDate; + + /* + * Possessor attribute + */ + + @JsonProperty("name") + @JsonPropertyDescription("Name of this possessor") + private String name; + + @JsonProperty("gender") + @JsonPropertyDescription("Gender of the possessor") + private String gender; + + @JsonProperty("birthDate") + @JsonPropertyDescription("BirthDate of the possessor") + private Long birthDate; + + /* + * issuer attribute + */ + + @JsonProperty("issuerName") + @JsonPropertyDescription("Issuer's name of this diploma") + private String issuerName; + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt113.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt113.java new file mode 100644 index 00000000..33b2d08c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt113.java @@ -0,0 +1,80 @@ +package com.webank.weid.protocol.cpt; + +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import lombok.Data; + +/** + * Metadata CPT + *

+ * Academic Degree Certificate: Academic degree certificate from authorized + * universities or educational institutions + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "id", + "major", + "issuanceDate", + "degree", + "degreeType", + "name", + "gender", + "birthDate", + "issuerName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt113 { + /* + * Certicate atrribute + */ + + @JsonProperty("id") + @JsonPropertyDescription("Id of this certificate") + private String id; + + @JsonProperty("issuanceDate") + @JsonPropertyDescription("IssuanceDate of this certificate") + private Long issuanceDate; + + @JsonProperty("major") + @JsonPropertyDescription("Major of this certificate") + private String major; + + @JsonProperty("degree") + @JsonPropertyDescription("Degree") + private String degree; + + @JsonProperty("degreeType") + @JsonPropertyDescription("Degree type") + private String degreeType; + + /* + * Possessor attribute + */ + + @JsonProperty("name") + @JsonPropertyDescription("Possessor's name of this certificate") + private String name; + + @JsonProperty("gender") + @JsonPropertyDescription("Gender of the Possessor") + private String gender; + + @JsonProperty("birthDate") + @JsonPropertyDescription("BirthDate of the Possessor") + private Long birthDate; + + /* + * issuer attribute + */ + + @JsonProperty("issuerName") + @JsonPropertyDescription("Issuer's name of this certificate") + private String issuerName; + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt114.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt114.java new file mode 100644 index 00000000..61487860 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt114.java @@ -0,0 +1,76 @@ +package com.webank.weid.protocol.cpt; + +import javax.annotation.Generated; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import lombok.Data; + +/** + * Metadata CPT + *

+ * Employee Demission Certificate: Employee demission certificate from + * authorized companies + * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "id", + "employBeginDate", + "employEndDate", + "reason", + "issuanceDate", + "position", + "name", + "issuerName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt114 { + /* + * Certicate atrribute + */ + + @JsonProperty("id") + @JsonPropertyDescription("Id of this certificate") + private String id; + + @JsonProperty("employBeginDate") + @JsonPropertyDescription("Date to begin employing") + private Long employBeginDate; + + @JsonProperty("employEndDate") + @JsonPropertyDescription("Date to end employing") + private Long employEndDate; + + @JsonProperty("reason") + @JsonPropertyDescription("Why to leave") + private String reason; + + @JsonProperty("issuanceDate") + @JsonPropertyDescription("IssuanceDate of this certificate") + private Long issuanceDate; + + @JsonProperty("position") + @JsonPropertyDescription("Position") + private String position; + + /* + * Possessor attribute + */ + @JsonProperty("name") + @JsonPropertyDescription("Possessor's name of this certificate") + private String name; + + /* + * issuer attribute + */ + + @JsonProperty("issuerName") + @JsonPropertyDescription("Name of this company(who issue this certificate)") + private String issuerName; + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt115.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt115.java new file mode 100644 index 00000000..c1c467f2 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt115.java @@ -0,0 +1,75 @@ +package com.webank.weid.protocol.cpt; + +import javax.annotation.Generated; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import lombok.Data; + +/** + * Metadata CPT + *

+ * Income Certificate: Income certificate from authorized companies + * + * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "id", + "employBeginDate", + "salary", + "income", + "issuanceDate", + "position", + "name", + "issuerName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt115 { + /* + * Certicate atrribute + */ + @JsonProperty("id") + @JsonPropertyDescription("Id of this certificate") + private String id; + + @JsonProperty("employBeginDate") + @JsonPropertyDescription("Date to begin employing") + private Long employBeginDate; + + @JsonProperty("salary") + @JsonPropertyDescription("Monthly salary") + private int salary; + + @JsonProperty("income") + @JsonPropertyDescription("Total Income including monthly salary and all bonus according to your achievement") + private int income; + + @JsonProperty("issuanceDate") + @JsonPropertyDescription("IssuanceDate of this certificate") + private Long issuanceDate; + + @JsonProperty("position") + @JsonPropertyDescription("Position") + private String position; + + /* + * Possessor attribute + */ + @JsonProperty("name") + @JsonPropertyDescription("Possessor's name of this certificate") + private String name; + + /* + * issuer attribute + */ + + @JsonProperty("issuerName") + @JsonPropertyDescription("Name of this company(who issue this certificate)") + private String issuerName; + +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/protocol/cpt/Cpt11Salt.java b/src/main/java/com/webank/weid/protocol/cpt/Cpt11Salt.java new file mode 100644 index 00000000..31005813 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/Cpt11Salt.java @@ -0,0 +1,130 @@ + +package com.webank.weid.protocol.cpt; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Generated; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; +import org.junit.experimental.theories.DataPoints; + + +/** + * test CPT + *

+ * Reserved CPT 11Salt + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "cptId", + "userId", + "userName" +}) +@Generated("jsonschema2pojo") +@Data +public class Cpt11Salt { + + /** + * CPT ID + * (Required) + * + */ + @JsonProperty("cptId") + @JsonPropertyDescription("CPT ID") + private String cptId; + /** + * User ID + * (Required) + * + */ + @JsonProperty("userId") + @JsonPropertyDescription("User ID") + private String userId; + /** + * User Name + * (Required) + * + */ + @JsonProperty("userName") + @JsonPropertyDescription("User Name") + private String userName; + @JsonIgnore + private Map additionalProperties = new LinkedHashMap(); + + /** + * getAdditionalProperties + * @return additionalProperties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + /** + * + * @param name name + * @param value value + */ + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Cpt11Salt.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("cptId"); + sb.append('='); + sb.append(((this.cptId == null)?"":this.cptId)); + sb.append(','); + sb.append("userId"); + sb.append('='); + sb.append(((this.userId == null)?"":this.userId)); + sb.append(','); + sb.append("userName"); + sb.append('='); + sb.append(((this.userName == null)?"":this.userName)); + sb.append(','); + sb.append("additionalProperties"); + sb.append('='); + sb.append(((this.additionalProperties == null)?"":this.additionalProperties)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode())); + result = ((result* 31)+((this.userName == null)? 0 :this.userName.hashCode())); + result = ((result* 31)+((this.cptId == null)? 0 :this.cptId.hashCode())); + result = ((result* 31)+((this.userId == null)? 0 :this.userId.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Cpt11Salt) == false) { + return false; + } + Cpt11Salt rhs = ((Cpt11Salt) other); + return (((((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties)))&&((this.userName == rhs.userName)||((this.userName!= null)&&this.userName.equals(rhs.userName))))&&((this.cptId == rhs.cptId)||((this.cptId!= null)&&this.cptId.equals(rhs.cptId))))&&((this.userId == rhs.userId)||((this.userId!= null)&&this.userId.equals(rhs.userId)))); + } + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/RawCptSchema.java b/src/main/java/com/webank/weid/protocol/cpt/RawCptSchema.java new file mode 100644 index 00000000..24a0653a --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/RawCptSchema.java @@ -0,0 +1,83 @@ +/** + * Copyright 2014-2021 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.webank.weid.protocol.cpt; + +import org.apache.commons.lang3.StringUtils; + +/** + * @author marsli + */ +public final class RawCptSchema { + + /** + * all attributes of this schema is required + */ + public final static String CPT101 = "{\"type\":\"object\",\"description\":\"Authorize data between WeIDs via the exposed Service Endpoint\",\"title\":\"Data Authorization Token\",\"properties\":{\"duration\":{\"type\":\"integer\",\"description\":\"Duration of Validity in seconds\"},\"fromWeId\":{\"type\":\"string\",\"description\":\"Authorize from this WeID\"},\"resourceId\":{\"type\":\"string\",\"description\":\"Authorized Resource ID\"},\"serviceUrl\":{\"type\":\"string\",\"description\":\"Service Endpoint URL\"},\"toWeId\":{\"type\":\"string\",\"description\":\"Authorize to this WeID\"}},\"required\":[\"duration\",\"fromWeId\",\"resourceId\",\"serviceUrl\",\"toWeId\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}";; + public final static String CPT102 = "{\"type\":\"object\",\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT103 = "{\"type\":\"object\",\"description\":\"Answer to meet the challenge\",\"title\":\"Authentication Answer\",\"properties\":{\"challenge\":{\"type\":\"object\",\"properties\":{\"nonce\":{\"type\":\"string\"},\"version\":{\"type\":\"integer\"},\"weId\":{\"type\":\"string\"}},\"description\":\"The challenge\"},\"id\":{\"type\":\"string\",\"description\":\"The entity's weidentity did\"},\"proof\":{\"type\":\"string\",\"description\":\"The proof\"}},\"required\":[\"challenge\",\"id\",\"proof\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT104 = "{\"type\":\"object\",\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT105 = "{\"type\":\"object\",\"description\":\"API Endpoint address disclosure\",\"title\":\"API Endpoint\",\"properties\":{\"argType\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"Argument types in sequence\"},\"description\":{\"type\":\"string\",\"description\":\"Description\"},\"endpointName\":{\"type\":\"string\",\"description\":\"Endpoint name\"},\"hostport\":{\"type\":\"string\",\"description\":\"Network host and port\"},\"id\":{\"type\":\"string\",\"description\":\"Owner WeIdentity DID\"},\"version\":{\"type\":\"string\",\"description\":\"API Version\"}},\"required\":[\"argType\",\"description\",\"endpointName\",\"hostport\",\"id\",\"version\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT106 = "{\"type\":\"object\",\"description\":\"Embedded Signature object for multi-sign\",\"title\":\"Embedded Signature\",\"properties\":{\"credentialList\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"claim\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"context\":{\"type\":\"string\"},\"cptId\":{\"type\":\"integer\"},\"expirationDate\":{\"type\":\"integer\"},\"hash\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"issuanceDate\":{\"type\":\"integer\"},\"issuer\":{\"type\":\"string\"},\"proof\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"string\"},\"orDefault\":{\"type\":\"string\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"proofType\":{\"type\":\"string\"},\"signature\":{\"type\":\"string\"},\"signatureThumbprint\":{\"type\":\"string\"}}},\"description\":\"Original credential list to be signed\"}},\"required\":[\"credentialList\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT107 = "{\"type\":\"object\",\"description\":\"Embedded Signature object for multi-sign\",\"title\":\"Embedded Signature\",\"properties\":{\"credentialList\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"claim\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"context\":{\"type\":\"string\"},\"cptId\":{\"type\":\"integer\"},\"credentialType\":{\"enum\":[\"ORIGINAL\",\"ZKP\",\"LITE1\"],\"type\":\"string\"},\"expirationDate\":{\"type\":\"integer\"},\"hash\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"issuanceDate\":{\"type\":\"integer\"},\"issuer\":{\"type\":\"string\"},\"proof\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"proofType\":{\"type\":\"string\"},\"salt\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"signature\":{\"type\":\"string\"},\"signatureThumbprint\":{\"type\":\"string\"},\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"valueFromProof\":{\"type\":\"object\"}}},\"description\":\"Original credential list to be signed\"}},\"required\":[\"credentialList\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT108 = "{\"type\":\"object\",\"description\":\"Trusted timestamping envelope\",\"title\":\"Trusted Timestamping\",\"properties\":{\"authoritySignature\":{\"type\":\"string\",\"description\":\"Signature value from Authority\"},\"claimHash\":{\"type\":\"string\",\"description\":\"Claim Hash\"},\"credentialList\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"claim\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"context\":{\"type\":\"string\"},\"cptId\":{\"type\":\"integer\"},\"credentialType\":{\"enum\":[\"ORIGINAL\",\"ZKP\",\"LITE1\"],\"type\":\"string\"},\"expirationDate\":{\"type\":\"integer\"},\"hash\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"issuanceDate\":{\"type\":\"integer\"},\"issuer\":{\"type\":\"string\"},\"proof\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"proofType\":{\"type\":\"string\"},\"salt\":{\"type\":\"object\",\"properties\":{\"get\":{\"type\":\"object\"},\"orDefault\":{\"type\":\"object\"},\"isEmpty\":{\"type\":\"boolean\"}}},\"signature\":{\"type\":\"string\"},\"signatureThumbprint\":{\"type\":\"string\"},\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"valueFromProof\":{\"type\":\"object\"}}},\"description\":\"Original credential list to be signed\"},\"timestamp\":{\"type\":\"integer\",\"description\":\"Timestamp\"},\"timestampAuthority\":{\"type\":\"string\",\"description\":\"Timestamp Authority\"}},\"required\":[\"authoritySignature\",\"claimHash\",\"credentialList\",\"timestamp\",\"timestampAuthority\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT109 = "{\"type\":\"object\",\"description\":\"Trusted Timestamp from authorized 3rd-party, or chain consensus\",\"title\":\"Trusted Timestamp\",\"properties\":{\"claimHash\":{\"type\":\"string\"},\"hashKey\":{\"type\":\"string\"},\"signatureList\":{\"type\":\"string\"},\"timestamp\":{\"type\":\"integer\"}},\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT110 = "{\"type\":\"object\",\"description\":\"Reserved CPT 110\",\"title\":\"metadata CPT\",\"properties\":{\"context\":{\"type\":\"string\",\"description\":\"context\"},\"cptId\":{\"type\":\"integer\",\"description\":\"CPT ID\"},\"credentialId\":{\"type\":\"string\",\"description\":\"credential ID\"},\"expirationDate\":{\"type\":\"integer\",\"description\":\"expirationDate\"},\"issuanceDate\":{\"type\":\"integer\",\"description\":\"issuanceDate\"},\"issuer\":{\"type\":\"string\",\"description\":\"issuer weid\"}},\"required\":[\"context\",\"cptId\",\"credentialId\",\"expirationDate\",\"issuanceDate\",\"issuer\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT111 = "{\"type\":\"object\",\"description\":\"Reserved CPT 111\",\"title\":\"User CPT\",\"properties\":{\"cptId\":{\"type\":\"string\",\"description\":\"CPT ID\"},\"credentialSignatureRequest\":{\"type\":\"string\",\"description\":\"credential Signature Request\",\"minimum\":1},\"userNonce\":{\"type\":\"string\",\"description\":\"User Nonce\"}},\"required\":[\"cptId\",\"credentialSignatureRequest\",\"userNonce\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT11 = "{\"type\":\"object\",\"description\":\"Reserved CPT 11\",\"title\":\"test CPT\",\"properties\":{\"cptId\":{\"type\":\"integer\",\"description\":\"CPT ID\",\"minimum\":1},\"gender\":{\"type\":\"string\",\"description\":\"Gender\",\"enum\":[\"MALE\",\"FEMALE\"]},\"tags\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"Registered Tags\",\"minItems\":1},\"userId\":{\"type\":\"string\",\"description\":\"User ID\"},\"userName\":{\"type\":\"string\",\"description\":\"User Name\",\"maxLength\":30}},\"required\":[\"cptId\",\"gender\",\"tags\",\"userId\",\"userName\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT11Salt = "{\"type\":\"object\",\"description\":\"Reserved CPT 11Salt\",\"title\":\"test CPT\",\"properties\":{\"cptId\":{\"type\":\"string\",\"description\":\"CPT ID\",\"minimum\":1},\"userId\":{\"type\":\"string\",\"description\":\"User ID\"},\"userName\":{\"type\":\"string\",\"description\":\"User Name\",\"maxLength\":30}},\"required\":[\"cptId\",\"userId\",\"userName\"],\"$schema\":\"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT112 = "{\"type\": \"object\", \"description\": \"Academic certificate from authorized universities or educational institutions\", \"title\": \"Diploma\", \"properties\": {\"id\": {\"type\": \"string\", \"description\": \"Id of this diploma\"},\"major\": {\"type\": \"string\", \"description\": \"Major of this diploma\"}, \"issuanceDate\": {\"type\": \"string\", \"description\": \"IssuanceDate of this diploma\"}, \"name\": {\"type\": \"string\", \"description\": \"Name of this possessor\"}, \"gender\": {\"type\": \"string\", \"description\": \"Gender of the possessor\", \"enum\": [\"MALE\", \"FEMALE\"]}, \"birthDate\": {\"type\": \"string\", \"description\": \"BirthDate of the possessor\"}, \"issuerName\": {\"type\": \"string\", \"description\": \"Issuer's name of this diploma\"}}, \"required\": [\"major\", \"issuanceDate\", \"name\", \"gender\", \"birthDate\", \"issuerName\"], \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT113 = "{\"type\": \"object\", \"description\": \"Academic degree certificate from authorized universities or educational institutions\", \"title\": \"Academic Degree Certificate\", \"properties\": {\"id\": {\"type\": \"string\", \"description\": \"Id of this certificate\"},\"issuanceDate\": {\"type\": \"string\", \"description\": \"IssuanceDate of this certificate\"}, \"major\": {\"type\": \"string\", \"description\": \"Major of this certificate\"}, \"degree\": {\"type\": \"string\", \"description\": \"Degree\", \"enum\": [ \"Bachelor\", \"Master\" ]}, \"degreeType\": {\"type\": \"string\", \"description\": \"Degree type\",\"enum\": [ \"Engineering\", \"Science\", \"Art\" ]}, \"name\": {\"type\": \"string\", \"description\": \"Possessor's name of this certificate\"}, \"gender\": {\"type\": \"string\", \"description\": \"Gender of the possessor\", \"enum\": [\"MALE\", \"FEMALE\"]}, \"birthDate\": {\"type\": \"string\", \"description\": \"BirthDate of the possessor\"}, \"issuerName\": {\"type\": \"string\", \"description\": \"Issuer's name of this certificate\"}}, \"required\": [\"major\", \"issuanceDate\", \"name\", \"degree\",\"degreeType\", \"gender\", \"birthDate\", \"issuerName\"], \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT114 = "{\"type\": \"object\", \"description\": \"Employee demission certificate from authorized companies\", \"title\": \"Employee Demission Certificate\", \"properties\": {\"id\": {\"type\": \"string\", \"description\": \"Id of this certificate\"},\"employBeginDate\": {\"type\": \"string\", \"description\": \"Date to begin employing\"}, \"employEndDate\": {\"type\": \"string\", \"description\": \"Date to end employing\"}, \"reason\": {\"type\": \"string\", \"description\": \"Why to leave\"}, \"issuanceDate\": {\"type\": \"string\", \"description\": \"IssuanceDate of this certificate\"}, \"position\": {\"type\": \"string\", \"description\": \"Position\"}, \"name\": {\"type\": \"string\", \"description\": \"Possessor's name of this certificate\"}, \"issuerName\": {\"type\": \"string\", \"description\": \"Name of this company(who issue this certificate)\"}}, \"required\": [\"employBeginDate\",\"employEndDate\", \"issuanceDate\", \"name\", \"position\",\"issuerName\"], \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"; + public final static String CPT115 = "{\"type\": \"object\", \"description\": \"Income certificate from authorized companies\", \"title\": \"Income Certificate\", \"properties\": {\"id\": {\"type\": \"string\", \"description\": \"Id of this certificate\"},\"employBeginDate\": {\"type\": \"string\", \"description\": \"Date to begin employing\"}, \"salary\": {\"type\": \"string\", \"description\": \"Monthly salary\"}, \"income\": {\"type\": \"string\", \"description\": \"Total Income including monthly salary and all bonus according to your achievement\"}, \"issuanceDate\": {\"type\": \"string\", \"description\": \"IssuanceDate of this certificate\"}, \"position\": {\"type\": \"string\", \"description\": \"Position\"}, \"name\": {\"type\": \"string\", \"description\": \"Possessor's name of this certificate\"}, \"issuerName\": {\"type\": \"string\", \"description\": \"Name of this company(who issue this certificate)\"}}, \"required\": [\"employBeginDate\",\"income\", \"issuanceDate\", \"position\",\"name\",\"issuerName\"], \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"; + + public static String getCptSchema(Integer cptId) { + switch (cptId) { + case 101: + return CPT101; + case 102: + return CPT102; + case 103: + return CPT103; + case 104: + return CPT104; + case 105: + return CPT105; + case 106: + return CPT106; + case 107: + return CPT107; + case 108: + return CPT108; + case 109: + return CPT109; + case 110: + return CPT110; + case 111: + return CPT111; + case 11: + return CPT11; + case 112: + return CPT112; + case 113: + return CPT113; + case 114: + return CPT114; + case 115: + return CPT115; + default: + return StringUtils.EMPTY; + } + } +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt101.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt101.java new file mode 100644 index 00000000..7fec8e1d --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt101.java @@ -0,0 +1,26 @@ + + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * CPT for data authorization. + * + * @author chaoxinhu 2020.2 + */ +@Data +//@Attributes(title = "Data Authorization Token", description = "Authorize data between WeIDs via the exposed Service Endpoint") +public class Cpt101 { + +// @Attributes(required = true, description = "Authorize from this WeID") + private String fromWeId; +// @Attributes(required = true, description = "Authorize to this WeID") + private String toWeId; +// @Attributes(required = true, description = "Service Endpoint URL") + private String serviceUrl; +// @Attributes(required = true, description = "Authorized Resource ID") + private String resourceId; +// @Attributes(required = true, description = "Duration of Validity in seconds") + private Long duration; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt102.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt102.java new file mode 100644 index 00000000..ccdcd4d0 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt102.java @@ -0,0 +1,15 @@ + + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * Credential for Challenge. + * + * @author Created by Junqi Zhang on 2019/4/9. + */ +@Data +public class Cpt102 { + +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt103.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt103.java new file mode 100644 index 00000000..934d5de3 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt103.java @@ -0,0 +1,24 @@ + + +package com.webank.weid.protocol.cpt.old; + +import com.webank.weid.protocol.base.Challenge; +import lombok.Data; + +/** + * Credential for authentication. The answer to meet the challenge. We package the answer into a + * Credential(CPT104) so the verifier can verify this answer. + * + * @author Created by Junqi Zhang on 2019/4/9. + */ +@Data +//@Attributes(title = "Authentication Answer", description = "Answer to meet the challenge") +public class Cpt103 { + +// @Attributes(required = true, description = "The entity's weidentity did") + private String id; +// @Attributes(required = true, description = "The challenge") + private Challenge challenge; +// @Attributes(required = true, description = "The proof") + private String proof; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt104.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt104.java new file mode 100644 index 00000000..902bc8cc --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt104.java @@ -0,0 +1,15 @@ + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * Confirmation for Policy. + * + * @author Created by Junqi Zhang on 2019/4/9. + */ +@Data +public class Cpt104 { + + +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt105.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt105.java new file mode 100644 index 00000000..76eac08e --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt105.java @@ -0,0 +1,29 @@ + + +package com.webank.weid.protocol.cpt.old; + +import java.util.List; +import lombok.Data; + +/** + * Api endpoint address disclosure. + * + * @author junqizhang, chaoxinhu 2019.8 + */ +@Data +//@Attributes(title = "API Endpoint", description = "API Endpoint address disclosure") +public class Cpt105 { + +// @Attributes(required = true, description = "Owner WeIdentity DID") + private String id; +// @Attributes(required = true, description = "Network host and port") + private String hostport; +// @Attributes(required = true, description = "Endpoint name") + private String endpointName; +// @Attributes(required = true, description = "Description") + private String description; +// @Attributes(required = true, description = "API Version") + private String version; +// @Attributes(required = true, description = "Argument types in sequence") + private List argType; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt106.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt106.java new file mode 100644 index 00000000..a69635e5 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt106.java @@ -0,0 +1,21 @@ + + +package com.webank.weid.protocol.cpt.old; + +import com.webank.weid.protocol.base.Credential; +import java.util.List; +import lombok.Data; + +/** + * Multiple signature to a Credential. + * + * @author chaoxinhu 2019.8 + */ + +@Data +//@Attributes(title = "Embedded Signature", description = "Embedded Signature object for multi-sign") +public class Cpt106 { + +// @Attributes(required = true, description = "Original credential list to be signed") + List credentialList; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt107.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt107.java new file mode 100644 index 00000000..a33742b9 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt107.java @@ -0,0 +1,21 @@ + + +package com.webank.weid.protocol.cpt.old; + +import com.webank.weid.protocol.base.CredentialPojo; +import java.util.List; +import lombok.Data; + +/** + * Multiple signature to a CredentialPojo. + * + * @author chaoxinhu 2019.8 + */ + +@Data +//@Attributes(title = "Embedded Signature", description = "Embedded Signature object for multi-sign") +public class Cpt107 { + +// @Attributes(required = true, description = "Original credential list to be signed") + List credentialList; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt108.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt108.java new file mode 100644 index 00000000..91213f20 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt108.java @@ -0,0 +1,49 @@ + + +package com.webank.weid.protocol.cpt.old; + +import com.webank.weid.protocol.base.CredentialPojo; +import java.util.List; +import lombok.Data; + +/** + * Trusted timestamping envelope. + * + * @author junqizhang 2019.11 + */ + +@Data +//@Attributes(title = "Trusted Timestamping", description = "Trusted timestamping envelope") +public class Cpt108 { + + /** + * information about timestamp authority. + */ +// @Attributes(required = true, description = "Timestamp Authority") + String timestampAuthority; + + /** + * caculate the hash from the credentials. + */ +// @Attributes(required = true, description = "Claim Hash") + String claimHash; + + /** + * trusted timestamping provided by the trusted third party or by the consensus of each node in + * the consortium chain. + */ +// @Attributes(required = true, description = "Timestamp") + Long timestamp; + + /** + * signed by Timestamp authority. authoritySignature = sign( hashKey ) + */ +// @Attributes(required = true, description = "Signature value from Authority") + String authoritySignature; + + /** + * The credential list to be signed with timestamp. + */ +// @Attributes(required = true, description = "Original credential list to be signed") + List credentialList; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt109.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt109.java new file mode 100644 index 00000000..0631801c --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt109.java @@ -0,0 +1,37 @@ + + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * Trusted timestamping envelope. + * + * @author junqizhang 2019.11 + */ + +@Data +//@Attributes(title = "Trusted Timestamp", description = "Trusted Timestamp from authorized 3rd-party, or chain consensus") +public class Cpt109 { + + /** + * calculate the hash from the entire list rather than from any single credential. + */ + String claimHash; + + /** + * trusted timestamp provided by the trusted third party or by the consensus of each node in + * the consortium chain. + */ + Long timestamp; + + /** + * hashKey = hash(claimHash + timestamp) hashKey will be the key in the smart contract. + */ + String hashKey; + + /** + * signed by Timestamp authority signature = sign( hashKey ). + */ + String signatureList; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11.java new file mode 100644 index 00000000..d57e0b3e --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11.java @@ -0,0 +1,28 @@ + + +package com.webank.weid.protocol.cpt.old; + +import java.util.List; +import lombok.Data; + +//import com.github.reinert.jjschema.Attributes; + +/** + * the CPT for test. + * @author Created by Junqi Zhang on 2019/4/3. + */ +@Data +//@Attributes(title = "test CPT", description = "Reserved CPT 11") +public class Cpt11 { + +//// @Attributes(required = true, description = "CPT ID", minimum = 1) + private Integer cptId; +//// @Attributes(required = true, description = "User ID") + private String userId; +//// @Attributes(required = true, description = "User Name", maxLength = 30) + private String userName; +//// @Attributes(required = true, description = "Registered Tags", minItems = 1) + private List tags; +//// @Attributes(required = true, description = "Gender", enums = {"MALE", "FEMALE"}) + private String gender; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt110.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt110.java new file mode 100644 index 00000000..515717e3 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt110.java @@ -0,0 +1,48 @@ + + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * User request issuer to sign credential. + * + * @author tonychen + */ +@Data +//@Attributes(title = "metadata CPT", description = "Reserved CPT 110") +public class Cpt110 { + +// @Attributes(required = true, description = "CPT ID") + private Integer cptId; + + /** + * credential id. + */ +// @Attributes(required = true, description = "credential ID") + private String credentialId; + + /** + * Required: The context field. + */ +// @Attributes(required = true, description = "context") + private String context; + + /** + * Required: The issuer WeIdentity DID. + */ +// @Attributes(required = true, description = "issuer weid") + private String issuer; + + /** + * Required: The create date. + */ +// @Attributes(required = true, description = "issuanceDate") + private Long issuanceDate; + + /** + * Required: The expire date. + */ +// @Attributes(required = true, description = "expirationDate") + private Long expirationDate; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt111.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt111.java new file mode 100644 index 00000000..95207e6d --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt111.java @@ -0,0 +1,22 @@ + + +package com.webank.weid.protocol.cpt.old; + +import lombok.Data; + +/** + * User request issuer to sign credential. + * + * @author tonychen + */ +@Data +//@Attributes(title = "User CPT", description = "Reserved CPT 111") +public class Cpt111 { + +// @Attributes(required = true, description = "CPT ID") + private String cptId; +// @Attributes(required = true, description = "credential Signature Request", minimum = 1) + private String credentialSignatureRequest; +// @Attributes(required = true, description = "User Nonce") + private String userNonce; +} diff --git a/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11Salt.java b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11Salt.java new file mode 100644 index 00000000..93a7e5d1 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/cpt/old/Cpt11Salt.java @@ -0,0 +1,24 @@ + + +package com.webank.weid.protocol.cpt.old; + +//import com.github.reinert.jjschema.Attributes; +import lombok.Data; + +/** + * the CPT for test. + * @author Created by Junqi Zhang on 2019/4/3. + */ +@Data +//@Attributes(title = "test CPT", description = "Reserved CPT 11Salt") +public class Cpt11Salt { + +//// @Attributes(required = true, description = "CPT ID", minimum = 1) + String cptId; + +//// @Attributes(required = true, description = "User ID") + String userId; + +//// @Attributes(required = true, description = "User Name", maxLength = 30) + String userName; +} diff --git a/src/main/java/com/webank/weid/protocol/inf/Hashable.java b/src/main/java/com/webank/weid/protocol/inf/Hashable.java new file mode 100644 index 00000000..83a84dd1 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/Hashable.java @@ -0,0 +1,7 @@ + + +package com.webank.weid.protocol.inf; + +public interface Hashable { + public String getHash(); +} diff --git a/src/main/java/com/webank/weid/protocol/inf/IArgs.java b/src/main/java/com/webank/weid/protocol/inf/IArgs.java new file mode 100644 index 00000000..c1c9d5b5 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/IArgs.java @@ -0,0 +1,9 @@ + + +package com.webank.weid.protocol.inf; + +/** + * 请求体. + */ +public interface IArgs { +} diff --git a/src/main/java/com/webank/weid/protocol/inf/IProof.java b/src/main/java/com/webank/weid/protocol/inf/IProof.java new file mode 100644 index 00000000..9511c176 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/IProof.java @@ -0,0 +1,41 @@ + + +package com.webank.weid.protocol.inf; + +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +/** + * proof接口. + * + * @author v_wbgyang + * + */ +public interface IProof { + + /** + * 从proof中获取key对应value. + * @param proof proofMap数据 + * @param key 要获取的数据的key + * @return 返回key的数据 + */ + public default Object getValueFromProof(Map proof, String key) { + if (proof != null) { + return proof.get(key); + } + return null; + } + + /** + * 将Object转换成String. + * @param obj 从proof中取出的object + * @return 返回key的字符串数据 + */ + public default String toString(Object obj) { + if (obj != null) { + return String.valueOf(obj); + } + return StringUtils.EMPTY; + } +} diff --git a/src/main/java/com/webank/weid/protocol/inf/IResult.java b/src/main/java/com/webank/weid/protocol/inf/IResult.java new file mode 100644 index 00000000..971fa556 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/IResult.java @@ -0,0 +1,10 @@ + + +package com.webank.weid.protocol.inf; + +/** + * 结果. + */ +public interface IResult { + +} diff --git a/src/main/java/com/webank/weid/protocol/inf/JsonSerializer.java b/src/main/java/com/webank/weid/protocol/inf/JsonSerializer.java new file mode 100644 index 00000000..7cf11076 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/JsonSerializer.java @@ -0,0 +1,14 @@ + + +package com.webank.weid.protocol.inf; + +import java.io.Serializable; + +import com.webank.weid.util.DataToolUtils; + +public interface JsonSerializer extends Serializable { + + public default String toJson() { + return DataToolUtils.serialize(this); + } +} diff --git a/src/main/java/com/webank/weid/protocol/inf/RawSerializer.java b/src/main/java/com/webank/weid/protocol/inf/RawSerializer.java new file mode 100644 index 00000000..7f8dd5c5 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/inf/RawSerializer.java @@ -0,0 +1,10 @@ + + +package com.webank.weid.protocol.inf; + +public interface RawSerializer extends JsonSerializer { + + public default String toRawData() { + return JsonSerializer.super.toJson(); + } +} diff --git a/src/main/java/com/webank/weid/protocol/request/AuthenticationArgs.java b/src/main/java/com/webank/weid/protocol/request/AuthenticationArgs.java new file mode 100644 index 00000000..d17cfecc --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/AuthenticationArgs.java @@ -0,0 +1,31 @@ + + +package com.webank.weid.protocol.request; + +import lombok.Data; + +/** + * The Arguments when setting Authentication for WeIdentity DID. + * + * @author afeexian 2022.9.9 + */ +@Data +public class AuthenticationArgs { + + //用户可以指定verification method id,也可以由系统指定 + /** + * Required: The method id. + */ + private String id; + + /** + * Required: The method controller. + */ + private String controller; + + /** + * Required: The public key. + */ + private String publicKey; + +} diff --git a/src/main/java/com/webank/weid/protocol/request/CptMapArgs.java b/src/main/java/com/webank/weid/protocol/request/CptMapArgs.java new file mode 100644 index 00000000..4339e2a8 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/CptMapArgs.java @@ -0,0 +1,34 @@ + + +package com.webank.weid.protocol.request; + +import java.util.Map; + +import lombok.Data; + +import com.webank.weid.constant.CptType; +import com.webank.weid.protocol.base.WeIdAuthentication; + +/** + * The Arguments for the SDK API register CPT. The cptJsonSchema is Map. + * + * @author lingfenghe + */ +@Data +public class CptMapArgs { + + /** + * Required: weId authority for this CPT. + */ + private WeIdAuthentication weIdAuthentication; + + /** + * Required: The json schema content defined for this CPT. + */ + private Map cptJsonSchema; + + /** + * cpt type, "ORIGINAL" or "ZKP". default:"ORIGINAL". + */ + private CptType cptType = CptType.ORIGINAL; +} diff --git a/src/main/java/com/webank/weid/protocol/request/CptStringArgs.java b/src/main/java/com/webank/weid/protocol/request/CptStringArgs.java new file mode 100644 index 00000000..82a68a7a --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/CptStringArgs.java @@ -0,0 +1,32 @@ + + +package com.webank.weid.protocol.request; + +import lombok.Data; + +import com.webank.weid.constant.CptType; +import com.webank.weid.protocol.base.WeIdAuthentication; + +/** + * This is a subclass, The Arguments for the SDK API register CPT. The cptJsonSchema is String. + * + * @author darwindu + */ +@Data +public class CptStringArgs { + + /** + * Required: weId authority for this CPT. + */ + private WeIdAuthentication weIdAuthentication; + + /** + * Required: The json schema content defined for this CPT. + */ + private String cptJsonSchema; + + /** + * cpt type, "ORIGINAL" or "ZKP". default:"ORIGINAL". + */ + private CptType cptType = CptType.ORIGINAL; +} diff --git a/src/main/java/com/webank/weid/protocol/request/CreateCredentialArgs.java b/src/main/java/com/webank/weid/protocol/request/CreateCredentialArgs.java index e33c58a5..2595ff5a 100644 --- a/src/main/java/com/webank/weid/protocol/request/CreateCredentialArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/CreateCredentialArgs.java @@ -1,28 +1,13 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +import java.util.Map; import lombok.Data; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments for the following SDK API: createCredential(). * @@ -49,10 +34,15 @@ public class CreateCredentialArgs { /** * Required: The claim data. */ - private String claim; + private Map claim; /** * Required: The private key structure used for signing. */ private WeIdPrivateKey weIdPrivateKey; + + /** + * Optional: The issuance date of the credential. + */ + private Long issuanceDate = null; } diff --git a/src/main/java/com/webank/weid/protocol/request/CreateCredentialPojoArgs.java b/src/main/java/com/webank/weid/protocol/request/CreateCredentialPojoArgs.java new file mode 100644 index 00000000..f9791f2e --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/CreateCredentialPojoArgs.java @@ -0,0 +1,63 @@ + + +package com.webank.weid.protocol.request; + +import lombok.Data; + +import com.webank.weid.constant.CredentialType; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.util.CredentialUtils; + +/** + * The Arguments for the following SDK API: createCredential(). + * + * @author chaoxinhu 2018.10 + */ +@Data +public class CreateCredentialPojoArgs { + + /** + * Required: The CPT type in standard integer format. + */ + private Integer cptId; + + /** + * Required: The issuer WeIdentity DID. + */ + private String issuer; + + /** + * Required: The expire date. + */ + private Long expirationDate; + + /** + * Required: The claim data. + */ + private T claim; + + /** + * Required: The private key structure used for signing. + */ + private WeIdAuthentication weIdAuthentication; + + /** + * Optional: The issuance date of the credential. + */ + private Long issuanceDate = null; + + /** + * 新增字段,issuer提前生成好的credential ID,对应credentialPojo里的ID. + */ + private String id = null; + + /** + * Optional:credential context. + */ + private String context = CredentialUtils.getDefaultCredentialContext(); + + /** + * credential type. + */ + private CredentialType type = CredentialType.ORIGINAL; +} diff --git a/src/main/java/com/webank/weid/protocol/request/CreateWeIdArgs.java b/src/main/java/com/webank/weid/protocol/request/CreateWeIdArgs.java index bef50358..c893ae83 100644 --- a/src/main/java/com/webank/weid/protocol/request/CreateWeIdArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/CreateWeIdArgs.java @@ -1,28 +1,11 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +package com.webank.weid.protocol.request; import lombok.Data; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments when creating WeIdentity DID. * diff --git a/src/main/java/com/webank/weid/protocol/request/RegisterAuthorityIssuerArgs.java b/src/main/java/com/webank/weid/protocol/request/RegisterAuthorityIssuerArgs.java index eb336757..c4c1d9c1 100644 --- a/src/main/java/com/webank/weid/protocol/request/RegisterAuthorityIssuerArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/RegisterAuthorityIssuerArgs.java @@ -1,28 +1,16 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.request; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.PresentationPolicyE; +import lombok.Data; + import com.webank.weid.protocol.base.AuthorityIssuer; import com.webank.weid.protocol.base.WeIdPrivateKey; -import lombok.Data; +import java.util.HashMap; +import java.util.Map; /** * The Arguments for SDK RegisterAuthorityIssuer. @@ -41,4 +29,19 @@ public class RegisterAuthorityIssuerArgs { * Required: The WeIdentity DID private key for sending transaction. */ private WeIdPrivateKey weIdPrivateKey; + + /** + * transfer RegisterAuthorityIssuerArgs class to weid-blockchain. + * @param args the RegisterAuthorityIssuerArgs object + * @return RegisterAuthorityIssuerArgs object in weid-blockchain + */ + public static com.webank.weid.blockchain.protocol.request.RegisterAuthorityIssuerArgs toBlockChain(RegisterAuthorityIssuerArgs args) { + com.webank.weid.blockchain.protocol.request.RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new com.webank.weid.blockchain.protocol.request.RegisterAuthorityIssuerArgs(); + com.webank.weid.blockchain.protocol.base.AuthorityIssuer authorityIssuer = AuthorityIssuer.toBlockChain(args.getAuthorityIssuer()); + registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuer); + com.webank.weid.blockchain.protocol.base.WeIdPrivateKey weIdPrivateKey = new com.webank.weid.blockchain.protocol.base.WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(args.getWeIdPrivateKey().getPrivateKey()); + registerAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); + return registerAuthorityIssuerArgs; + } } diff --git a/src/main/java/com/webank/weid/protocol/request/RegisterCptArgs.java b/src/main/java/com/webank/weid/protocol/request/RegisterCptArgs.java deleted file mode 100644 index 76ea21cf..00000000 --- a/src/main/java/com/webank/weid/protocol/request/RegisterCptArgs.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.protocol.request; - -import com.webank.weid.protocol.base.WeIdPrivateKey; - -import lombok.Data; - -/** - * The Arguments for the SDK API register CPT. - * - * @author lingfenghe - */ -@Data -public class RegisterCptArgs { - - /** - * Required: The json schema content defined for this CPT. - */ - private String cptJsonSchema; - - /** - * Required: The weIdentity DID of the publisher who register this CPT. - */ - private String cptPublisher; - - /** - * Required: The private key for the publisher who register this CPT. - */ - private WeIdPrivateKey cptPublisherPrivateKey; -} diff --git a/src/main/java/com/webank/weid/protocol/request/RemoveAuthorityIssuerArgs.java b/src/main/java/com/webank/weid/protocol/request/RemoveAuthorityIssuerArgs.java index 4afa3055..bf622886 100644 --- a/src/main/java/com/webank/weid/protocol/request/RemoveAuthorityIssuerArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/RemoveAuthorityIssuerArgs.java @@ -1,28 +1,11 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +package com.webank.weid.protocol.request; import lombok.Data; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments for SDK API RemoveAuthorityIssuer. * diff --git a/src/main/java/com/webank/weid/protocol/request/ServiceArgs.java b/src/main/java/com/webank/weid/protocol/request/ServiceArgs.java new file mode 100644 index 00000000..d9e7f508 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/ServiceArgs.java @@ -0,0 +1,31 @@ + + +package com.webank.weid.protocol.request; + +import lombok.Data; + +/** + * The Arguments when setting services. + * + * @author tonychen 2020.4.24 + */ +@Data +public class ServiceArgs { + + //用户可以指定service id,也可以由系统指定 + /** + * Required: The service id. + */ + private String id; + + /** + * Required: service type. + */ + private String type; + + /** + * Required: service endpoint. + */ + private String serviceEndpoint; + +} diff --git a/src/main/java/com/webank/weid/protocol/request/SetAuthenticationArgs.java b/src/main/java/com/webank/weid/protocol/request/SetAuthenticationArgs.java index 09b56c28..a796aeae 100644 --- a/src/main/java/com/webank/weid/protocol/request/SetAuthenticationArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/SetAuthenticationArgs.java @@ -1,28 +1,11 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +package com.webank.weid.protocol.request; import lombok.Data; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments when setting Authentication for WeIdentity DID. * @@ -36,11 +19,6 @@ public class SetAuthenticationArgs { */ private String weId; - /** - * Required: The type. - */ - private String type; - /** * Required: The owner. */ diff --git a/src/main/java/com/webank/weid/protocol/request/SetPublicKeyArgs.java b/src/main/java/com/webank/weid/protocol/request/SetPublicKeyArgs.java index 0577a75f..4c559b40 100644 --- a/src/main/java/com/webank/weid/protocol/request/SetPublicKeyArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/SetPublicKeyArgs.java @@ -1,28 +1,13 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +package com.webank.weid.protocol.request; import lombok.Data; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.constant.WeIdConstant.PublicKeyType; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments when setting Public Key for WeIdentity DID. * @@ -39,7 +24,7 @@ public class SetPublicKeyArgs { /** * Required: The type. */ - private String type = "Secp256k1"; + private PublicKeyType type = PublicKeyType.ECDSA; /** * Required: The owner. @@ -55,4 +40,12 @@ public class SetPublicKeyArgs { * Required: The WeIdentity DID private key. */ private WeIdPrivateKey userWeIdPrivateKey; + + /** + * nothing to do. + * @param type the public key type + */ + public void setType(PublicKeyType type) { + this.type = type; + } } diff --git a/src/main/java/com/webank/weid/protocol/request/SetServiceArgs.java b/src/main/java/com/webank/weid/protocol/request/SetServiceArgs.java index 4f7e1b18..6bfdafe9 100644 --- a/src/main/java/com/webank/weid/protocol/request/SetServiceArgs.java +++ b/src/main/java/com/webank/weid/protocol/request/SetServiceArgs.java @@ -1,28 +1,11 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.request; -import com.webank.weid.protocol.base.WeIdPrivateKey; +package com.webank.weid.protocol.request; import lombok.Data; +import com.webank.weid.protocol.base.WeIdPrivateKey; + /** * The Arguments when setting services. * diff --git a/src/main/java/com/webank/weid/protocol/request/TransactionArgs.java b/src/main/java/com/webank/weid/protocol/request/TransactionArgs.java new file mode 100644 index 00000000..69fa9fbf --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/TransactionArgs.java @@ -0,0 +1,44 @@ +package com.webank.weid.protocol.request; + +import lombok.Getter; +import lombok.Setter; + +/** + * 离线交易的参数. + * + * @author tonychen 2020年4月4日 + */ +@Getter +@Setter +public class TransactionArgs { + + /** + * 每条请求对应的ID,唯一标识. + */ + private String requestId; + + /** + * 交易上链需要调用的方法名. + */ + private String method; + + /** + * 交易参数. + */ + private String args; + + /** + * 交易额外的信息. + */ + private String extra; + + /** + * 交易发生时的时间戳. + */ + private Long timeStamp; + + /** + * 批次,目前是按天. + */ + private String batch; +} diff --git a/src/main/java/com/webank/weid/protocol/request/UpdateCptArgs.java b/src/main/java/com/webank/weid/protocol/request/UpdateCptArgs.java deleted file mode 100644 index a8edb0e4..00000000 --- a/src/main/java/com/webank/weid/protocol/request/UpdateCptArgs.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.protocol.request; - -import com.webank.weid.protocol.base.WeIdPrivateKey; - -import lombok.Data; - -/** - * The Arguments for the SDK API update CPT. - * - * @author lingfenghe - */ -@Data -public class UpdateCptArgs { - - /** - * Required: the id for the CPT. - */ - private Integer cptId; - - /** - * Required: the json schema content defined for this CPT. - */ - private String cptJsonSchema; - - /** - * Required: the WeIdentity DID of the publisher who register this CPT. - */ - private String cptPublisher; - - /** - * Required: the private key for the publisher who register this CPT. - */ - private WeIdPrivateKey cptPublisherPrivateKey; -} diff --git a/src/main/java/com/webank/weid/protocol/request/VerifyCredentialArgs.java b/src/main/java/com/webank/weid/protocol/request/VerifyCredentialArgs.java deleted file mode 100644 index f984ab7d..00000000 --- a/src/main/java/com/webank/weid/protocol/request/VerifyCredentialArgs.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.protocol.request; - -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdPublicKey; - -import lombok.Data; - -/** - * The Arguments for the following SDK API: verifyCredential(). - * - * @author chaoxinhu 2018.10 - */ -@Data -public class VerifyCredentialArgs { - - /** - * Required: The Credential content. - */ - private Credential credential; - - /** - * Optional: The public key passed in. - */ - private WeIdPublicKey weIdPublicKey; -} diff --git a/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/GetTimestampRequest.java b/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/GetTimestampRequest.java new file mode 100644 index 00000000..043e3b4d --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/GetTimestampRequest.java @@ -0,0 +1,15 @@ + + +package com.webank.weid.protocol.request.timestamp.wesign; + +import lombok.Data; + +@Data +public class GetTimestampRequest { + String webankAppId; + String version = "1.0.0"; + String nonce; + String sign; + String plainHash; + String hashAlg = "SHA1"; +} diff --git a/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/VerifyTimestampRequest.java b/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/VerifyTimestampRequest.java new file mode 100644 index 00000000..2a32eea1 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/request/timestamp/wesign/VerifyTimestampRequest.java @@ -0,0 +1,16 @@ + + +package com.webank.weid.protocol.request.timestamp.wesign; + +import lombok.Data; + +@Data +public class VerifyTimestampRequest { + String webankAppId; + String version = "1.0.0"; + String nonce; + String sign; + String plainHash; + String b64TimeStamp; + String hashAlg = "SHA1"; +} diff --git a/src/main/java/com/webank/weid/protocol/response/CreateWeIdDataResult.java b/src/main/java/com/webank/weid/protocol/response/CreateWeIdDataResult.java index f22ddf72..39d731d6 100644 --- a/src/main/java/com/webank/weid/protocol/response/CreateWeIdDataResult.java +++ b/src/main/java/com/webank/weid/protocol/response/CreateWeIdDataResult.java @@ -1,29 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.response; +import lombok.Data; + import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.base.WeIdPublicKey; -import lombok.Data; - /** * The response result for creating WeIdentity DID. * diff --git a/src/main/java/com/webank/weid/protocol/response/ResolveEventLogResult.java b/src/main/java/com/webank/weid/protocol/response/ResolveEventLogResult.java new file mode 100644 index 00000000..be702f6d --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/ResolveEventLogResult.java @@ -0,0 +1,28 @@ +package com.webank.weid.protocol.response; + +import lombok.Data; + +import com.webank.weid.constant.ResolveEventLogStatus; + +@Data +public class ResolveEventLogResult { + + private ResolveEventLogStatus resultStatus; + + private Integer previousBlock; + + private static final int PREVIOUS_BLOCK = -32768; + + /** + * set value for resultStatus. + * + * @param resolveEventLogStatus the enum is ResolveEventLogStatus. + */ + public void setResolveEventLogStatus(ResolveEventLogStatus resolveEventLogStatus) { + + if (!ResolveEventLogStatus.STATUS_SUCCESS.equals(resolveEventLogStatus)) { + this.previousBlock = PREVIOUS_BLOCK; + } + this.resultStatus = resolveEventLogStatus; + } +} diff --git a/src/main/java/com/webank/weid/protocol/response/ResponseData.java b/src/main/java/com/webank/weid/protocol/response/ResponseData.java index 28b4f79d..cdc5f7f6 100644 --- a/src/main/java/com/webank/weid/protocol/response/ResponseData.java +++ b/src/main/java/com/webank/weid/protocol/response/ResponseData.java @@ -1,28 +1,12 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.protocol.response; -import com.webank.weid.constant.ErrorCode; +package com.webank.weid.protocol.response; +import com.webank.weid.blockchain.protocol.response.TransactionInfo; import lombok.Data; +import com.webank.weid.constant.ErrorCode; + /** * The internal base response result class. * @@ -32,34 +16,84 @@ @Data public class ResponseData { + /** + * The generic type result object. + */ private T result; - private Integer errorCode = ErrorCode.SUCCESS.getCode(); - private String errorMessage = ErrorCode.SUCCESS.getCodeDesc(); + + /** + * The error code. + */ + private Integer errorCode; + + /** + * The error message. + */ + private String errorMessage; + + /** + * The blockchain transaction info. Note that this transaction only becomes valid (not null nor + * blank) when a successful transaction is sent to chain with a block generated. + */ + private TransactionInfo transactionInfo = null; /** * Instantiates a new response data. */ public ResponseData() { + this.setErrorCode(ErrorCode.SUCCESS); } /** - * Instantiates a new response data. + * Instantiates a new response data. Transaction info is left null to avoid unnecessary boxing. * * @param result the result * @param errorCode the return code */ public ResponseData(T result, ErrorCode errorCode) { this.result = result; - this.errorCode = errorCode.getCode(); - this.errorMessage = errorCode.getCodeDesc(); + if (errorCode != null) { + this.errorCode = errorCode.getCode(); + this.errorMessage = errorCode.getCodeDesc(); + } } /** - * Instantiates a new response data. + * Instantiates a new response data with transaction info. * * @param result the result * @param errorCode the return code - * @param errorMessage the return message + * @param transactionInfo transactionInfo + */ + public ResponseData(T result, ErrorCode errorCode, TransactionInfo transactionInfo) { + this.result = result; + if (errorCode != null) { + this.errorCode = errorCode.getCode(); + this.errorMessage = errorCode.getCodeDesc(); + } + if (transactionInfo != null) { + this.transactionInfo = transactionInfo; + } + } + + /** + * set a ErrorCode type errorCode. + * + * @param errorCode the errorCode + */ + public void setErrorCode(ErrorCode errorCode) { + if (errorCode != null) { + this.errorCode = errorCode.getCode(); + this.errorMessage = errorCode.getCodeDesc(); + } + } + + /** + * Instantiates a new Response data based on the error code and error message. + * + * @param result the result + * @param errorCode code number + * @param errorMessage errorMessage */ public ResponseData(T result, Integer errorCode, String errorMessage) { this.result = result; diff --git a/src/main/java/com/webank/weid/protocol/response/RsvSignature.java b/src/main/java/com/webank/weid/protocol/response/RsvSignature.java index 3b812708..6bb2cb71 100644 --- a/src/main/java/com/webank/weid/protocol/response/RsvSignature.java +++ b/src/main/java/com/webank/weid/protocol/response/RsvSignature.java @@ -1,27 +1,18 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.protocol.response; +import com.webank.weid.protocol.base.AuthenticationProperty; +import com.webank.weid.protocol.base.ServiceProperty; +import com.webank.weid.protocol.base.WeIdDocument; import lombok.Data; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Uint8; + +import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32; +import org.fisco.bcos.sdk.abi.datatypes.generated.Uint8; + +import java.util.ArrayList; +import java.util.List; + /** * The internal base RSV signature data class. @@ -45,4 +36,35 @@ public class RsvSignature { * The s value. */ private Bytes32 s; + + /** + * todo support sm2 + */ +// private Bytes32 pub; + + /** + * transfer RsvSignature from weid-blockchain. + * @param signature the RsvSignature class in weid-blockchain + * @return RsvSignature + */ + public static RsvSignature fromBlockChain(com.webank.weid.blockchain.protocol.response.RsvSignature signature) { + RsvSignature rsvSignature = new RsvSignature(); + rsvSignature.setV(signature.getV()); + rsvSignature.setS(signature.getS()); + rsvSignature.setR(signature.getR()); + return rsvSignature; + } + + /** + * transfer RsvSignature to weid-blockchain. + * @param signature the RsvSignature class + * @return RsvSignature + */ + public static com.webank.weid.blockchain.protocol.response.RsvSignature toBlockChain(RsvSignature signature) { + com.webank.weid.blockchain.protocol.response.RsvSignature rsvSignature = new com.webank.weid.blockchain.protocol.response.RsvSignature(); + rsvSignature.setV(signature.getV()); + rsvSignature.setS(signature.getS()); + rsvSignature.setR(signature.getR()); + return rsvSignature; + } } diff --git a/src/main/java/com/webank/weid/protocol/response/WeIdListResult.java b/src/main/java/com/webank/weid/protocol/response/WeIdListResult.java new file mode 100644 index 00000000..e11504d6 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/WeIdListResult.java @@ -0,0 +1,17 @@ +package com.webank.weid.protocol.response; + +import java.util.List; + +import lombok.Data; + +/** + * get WeId and errorCode by pubkeyList response. + * + */ +@Data +public class WeIdListResult { + + private List weIdList; + + private List errorCodeList; +} diff --git a/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/AccessTokenResponse.java b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/AccessTokenResponse.java new file mode 100644 index 00000000..03b8f1d5 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/AccessTokenResponse.java @@ -0,0 +1,21 @@ + + +package com.webank.weid.protocol.response.timestamp.wesign; + +import lombok.Data; + +/** + * Access Token response. + * + * @author darwindu, imported by chaoxinhu, 2019/5/8 + **/ +@Data +public class AccessTokenResponse { + + private int code; + private String msg; + private String transactionTime; + private String access_token; + private String expire_time; + private int expire_in; +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/GetTimestampResponse.java b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/GetTimestampResponse.java new file mode 100644 index 00000000..36df02c0 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/GetTimestampResponse.java @@ -0,0 +1,35 @@ + + +package com.webank.weid.protocol.response.timestamp.wesign; + +import lombok.Data; + +/** + * Get timestamp response. + * + * @author chaoxinhu + **/ +@Data +public class GetTimestampResponse { + + private int code; + private String msg; + private String transactionTime; + private String bizSeqNo; + private Result result; + + @Data + public class Result { + + private String bizSeqNo; + private String transactionTime; + private TimestampData data; + + @Data + public class TimestampData { + + private String b64TimeStamp; + } + } + +} diff --git a/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/SignTicketResponse.java b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/SignTicketResponse.java new file mode 100644 index 00000000..43094703 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/SignTicketResponse.java @@ -0,0 +1,28 @@ + + +package com.webank.weid.protocol.response.timestamp.wesign; + +import java.util.List; + +import lombok.Data; + +/** + * Sign ticket response. + * + * @author darwindu, imported by chaoxinhu, 2019/5/8 + **/ +@Data +public class SignTicketResponse { + + private int code; + private String msg; + private String transactionTime; + private List tickets; + + @Data + public class Ticket { + private String value; + private int expire_id; + private String expire_time; + } +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/VerifyTimestampResponse.java b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/VerifyTimestampResponse.java new file mode 100644 index 00000000..b4399d37 --- /dev/null +++ b/src/main/java/com/webank/weid/protocol/response/timestamp/wesign/VerifyTimestampResponse.java @@ -0,0 +1,38 @@ + + +package com.webank.weid.protocol.response.timestamp.wesign; + +import java.util.Date; + +import lombok.Data; + +/** + * Verify timestamp response. + * + * @author chaoxinhu + **/ +@Data +public class VerifyTimestampResponse { + + private int code; + private String msg; + private String transactionTime; + private String bizSeqNo; + private Result result; + + @Data + public class Result { + + private String bizSeqNo; + private String transactionTime; + private TimestampData data; + + @Data + public class TimestampData { + + private Date signTime; + private Boolean verifyResult; + } + } + +} diff --git a/src/main/java/com/webank/weid/rpc/AuthorityIssuerService.java b/src/main/java/com/webank/weid/rpc/AuthorityIssuerService.java deleted file mode 100644 index 235cdc1d..00000000 --- a/src/main/java/com/webank/weid/rpc/AuthorityIssuerService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.rpc; - -import com.webank.weid.protocol.base.AuthorityIssuer; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; -import com.webank.weid.protocol.response.ResponseData; - -/** - * Service interface for operations on Authority Issuer. - * - * @author chaoxinhu 2018.10 - */ -public interface AuthorityIssuerService { - - /** - * Register a new Authority Issuer on Chain. - * - *

The input argument actually includes: WeIdentity DID, Name, CreateDate, and Accumulator - * Value. They will be stored into the 3 fields on the chain: the Bytes32 field (Name); the Int - * field (create date); the Dynamic Bytes field (accValue). The data Read and Write sequence is - * fixed in the above mentioned order. - * - * @param args the args - * @return true if succeeds, false otherwise - */ - ResponseData registerAuthorityIssuer(RegisterAuthorityIssuerArgs args); - - /** - * Remove a new Authority Issuer on Chain. - * - * @param args the args - * @return true if succeeds, false otherwise - */ - ResponseData removeAuthorityIssuer(RemoveAuthorityIssuerArgs args); - - /** - * Check whether the given WeIdentity DID is an authority issuer, or not. - * - * @param weId the WeIdentity DID - * @return true if yes, false otherwise - */ - ResponseData isAuthorityIssuer(String weId); - - /** - * Query the authority issuer information from a given WeIdentity DID. - * - * @param weId the WeIdentity DID - * @return authority issuer info - */ - ResponseData queryAuthorityIssuerInfo(String weId); -} diff --git a/src/main/java/com/webank/weid/rpc/CptService.java b/src/main/java/com/webank/weid/rpc/CptService.java deleted file mode 100644 index 5ef439b2..00000000 --- a/src/main/java/com/webank/weid/rpc/CptService.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.rpc; - -import com.webank.weid.protocol.base.Cpt; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.UpdateCptArgs; -import com.webank.weid.protocol.response.ResponseData; - -/** - * Service interface for operation on CPT (Claim protocol Type). - * - * @author lingfenghe - */ -public interface CptService { - - /** - * Register a new CPT to the blockchain. - * - * @param args the args - * @return The registered CPT info - */ - ResponseData registerCpt(RegisterCptArgs args); - - /** - * Query the latest CPT version. - * - * @param cptId the cpt id - * @return The registered CPT info - */ - ResponseData queryCpt(Integer cptId); - - /** - * Update the data fields of a registered CPT. - * - * @param args the args - * @return The updated CPT info - */ - ResponseData updateCpt(UpdateCptArgs args); -} diff --git a/src/main/java/com/webank/weid/rpc/CredentialService.java b/src/main/java/com/webank/weid/rpc/CredentialService.java deleted file mode 100644 index de3815a9..00000000 --- a/src/main/java/com/webank/weid/rpc/CredentialService.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.rpc; - -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; - -/** - * Service interface for operations on Credentials. - * - * @author chaoxinhu 2018.10 - */ -public interface CredentialService { - - /** - * Generate a credential. - * - * @param args the args - * @return credential - */ - ResponseData createCredential(CreateCredentialArgs args); - - /** - * Verify the validity of a credential. Public key will be fetched from chain. - * - * @param args the args - * @return the verification result. True if yes, false otherwise with exact verify error codes - * in ResponseData - */ - ResponseData verifyCredential(Credential args); - - /** - * Verify the validity of a credential. Public key must be provided. - * - * @param args the args - * @return the verification result. True if yes, false otherwise with exact verify error codes - * in ResponseData - */ - ResponseData verifyCredentialWithSpecifiedPubKey(VerifyCredentialArgs args); -} diff --git a/src/main/java/com/webank/weid/rpc/WeIdService.java b/src/main/java/com/webank/weid/rpc/WeIdService.java deleted file mode 100644 index 65a30946..00000000 --- a/src/main/java/com/webank/weid/rpc/WeIdService.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.rpc; - -import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; - -/** - * Service interface for operations on WeIdentity DID. - * - * @author tonychen - */ -public interface WeIdService { - - /** - * Create a WeIdentity DID without a keypair. SDK will generate a keypair for the caller. - * - * @return a data set including a WeIdentity DID and a keypair - */ - ResponseData createWeId(); - - /** - * Create a WeIdentity DID from the provided public key. - * - * @param createWeIdArgs you need to input a public key - * @return WeIdentity DID - */ - ResponseData createWeId(CreateWeIdArgs createWeIdArgs); - - /** - * Query WeIdentity DID document. - * - * @param weId the WeIdentity DID - * @return WeIdentity document in json type - */ - ResponseData getWeIdDocumentJson(String weId); - - /** - * Query WeIdentity DID document. - * - * @param weId the WeIdentity DID - * @return weId document in java object type - */ - ResponseData getWeIdDocument(String weId); - - /** - * Set public key in the WeIdentity DID Document. - * - * @param setPublicKeyArgs the set public key args - * @return true if the "set" operation succeeds, false otherwise. - */ - ResponseData setPublicKey(SetPublicKeyArgs setPublicKeyArgs); - - /** - * Set service properties. - * - * @param setServiceArgs your service name and endpoint - * @return true if the "set" operation succeeds, false otherwise. - */ - ResponseData setService(SetServiceArgs setServiceArgs); - - /** - * Set authentications in WeIdentity DID. - * - * @param setAuthenticationArgs A public key is needed. - * @return true if the "set" operation succeeds, false otherwise. - */ - ResponseData setAuthentication(SetAuthenticationArgs setAuthenticationArgs); - - /** - * Check if the WeIdentity DID exists on chain. - * - * @return true if exists, false otherwise. - */ - ResponseData isWeIdExist(String weId); -} diff --git a/src/main/java/com/webank/weid/service/BaseService.java b/src/main/java/com/webank/weid/service/BaseService.java deleted file mode 100644 index 2b7ed781..00000000 --- a/src/main/java/com/webank/weid/service/BaseService.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.service; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.math.BigInteger; - -import org.bcos.channel.client.Service; -import org.bcos.contract.tools.ToolConf; -import org.bcos.web3j.crypto.Credentials; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.GenCredential; -import org.bcos.web3j.protocol.Web3j; -import org.bcos.web3j.protocol.channel.ChannelEthereumService; -import org.bcos.web3j.tx.Contract; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import com.webank.weid.constant.WeIdConstant; -import com.webank.weid.exception.InitWeb3jException; -import com.webank.weid.exception.LoadContractException; -import com.webank.weid.exception.PrivateKeyIllegalException; - -/** - * The BaseService for other RPC classes. - * - * @author tonychen - */ -public abstract class BaseService { - - private static final Logger logger = LoggerFactory.getLogger(BaseService.class); - - protected static ApplicationContext context; - - protected static Credentials credentials; - - private static Web3j web3j; - - static { - context = new ClassPathXmlApplicationContext("applicationContext.xml"); - } - - /** - * Load config. - * - * @return true, if successful - */ - private static boolean loadConfig() { - return (initWeb3j() && initCredentials()); - } - - private static boolean initWeb3j() { - Service service = context.getBean(Service.class); - try { - service.run(); - } catch (Exception e) { - logger.error("[BaseService] Service init failed. ", e); - throw new InitWeb3jException(e); - } - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - web3j = Web3j.build(channelEthereumService); - if (null == web3j) { - logger.error("[BaseService] web3j init failed. "); - return false; - } - return true; - } - - /** - * Inits the credentials. - * - * @return true, if successful - */ - private static boolean initCredentials() { - ToolConf toolConf = context.getBean(ToolConf.class); - logger.info("begin init credentials"); - credentials = GenCredential.create(toolConf.getPrivKey()); - - if (null == credentials) { - logger.error("[BaseService] credentials init failed. "); - return false; - } - return true; - } - - /** - * Gets the web3j. - * - * @return the web3j - */ - protected static Web3j getWeb3j() { - if (null == web3j) { - if (!initWeb3j()) { - throw new InitWeb3jException(); - } - } - return web3j; - } - - private static Object loadContract( - String contractAddress, - Credentials credentials, - Class cls) throws NoSuchMethodException, IllegalAccessException, - InvocationTargetException { - Object contract; - Method method = cls.getMethod( - "load", - String.class, - Web3j.class, - Credentials.class, - BigInteger.class, - BigInteger.class - ); - - contract = method.invoke( - null, - contractAddress, - web3j, - credentials, - WeIdConstant.GAS_PRICE, - WeIdConstant.GAS_LIMIT - ); - return contract; - } - - /** - * Reload contract. - * - * @param contractAddress the contract address - * @param cls the class - * @return the contract - */ - protected static Contract reloadContract( - String contractAddress, - String privateKey, - Class cls) { - Credentials credentials; - try { - ECKeyPair keyPair = ECKeyPair.create(new BigInteger(privateKey)); - credentials = Credentials.create(keyPair); - } catch (Exception e) { - throw new PrivateKeyIllegalException(e); - } - - Object contract = null; - if (null == web3j || !initWeb3j()) { - throw new InitWeb3jException(); - } - try { - // load contract - contract = loadContract(contractAddress, credentials, cls); - logger.info(cls.getSimpleName() + " init succ"); - } catch (Exception e) { - logger.error("load contract :{} failed. Error message is :{}", - cls.getSimpleName(), e); - throw new LoadContractException(); - } - - if (contract == null) { - throw new LoadContractException(); - } - return (Contract) contract; - } - - /** - * Gets the contract service. - * - * @param contractAddress the contract address - * @param cls the class - * @return the contract service - */ - protected static Contract getContractService(String contractAddress, Class cls) { - - Object contract = null; - if (null == web3j || null == credentials) { - loadConfig(); - } - try { - // load contract - contract = loadContract(contractAddress, credentials, cls); - logger.info(cls.getSimpleName() + " init succ"); - - } catch (Exception e) { - logger.error("load contract :{} failed. Error message is :{}", - cls.getSimpleName(), e); - throw new LoadContractException(); - } - - if (contract == null) { - throw new LoadContractException(); - } - return (Contract) contract; - } -} diff --git a/src/main/java/com/webank/weid/service/console/CredentialServiceConsole.java b/src/main/java/com/webank/weid/service/console/CredentialServiceConsole.java new file mode 100644 index 00000000..3593c99b --- /dev/null +++ b/src/main/java/com/webank/weid/service/console/CredentialServiceConsole.java @@ -0,0 +1,1128 @@ +package com.webank.weid.service.console; + +import com.networknt.schema.ValidationMessage; +import com.webank.wedpr.selectivedisclosure.VerifierClient; +import com.webank.wedpr.selectivedisclosure.VerifierResult; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.CredentialFieldDisclosureValue; +import com.webank.weid.constant.CredentialType; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.cpt.Cpt101; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.util.*; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.*; + +public class CredentialServiceConsole { + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(CredentialServiceConsole.class); + private static final String NOT_DISCLOSED = + CredentialFieldDisclosureValue.NOT_DISCLOSED.getStatus().toString(); + private static final String DISCLOSED = + CredentialFieldDisclosureValue.DISCLOSED.getStatus().toString(); + private static final String EXISTED = + CredentialFieldDisclosureValue.EXISTED.getStatus().toString(); + private static final WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + + //创建普通Credential + public ResponseData createCredential(CreateCredentialPojoArgs args) { + + try { + ErrorCode innerResponseData = + CredentialPojoUtils.isCreateCredentialPojoArgsValid(args); + if (ErrorCode.SUCCESS.getCode() != innerResponseData.getCode()) { + logger.error("Create Credential Args illegal: {}", + innerResponseData.getCodeDesc()); + return new ResponseData<>(null, innerResponseData); + } + CredentialPojo result = new CredentialPojo(); + String context = CredentialUtils.getDefaultCredentialContext(); + result.setContext(context); + if (StringUtils.isBlank(args.getId())) { + result.setId(UUID.randomUUID().toString()); + } else { + result.setId(args.getId()); + } + result.setCptId(args.getCptId()); + Long issuanceDate = args.getIssuanceDate(); + if (issuanceDate == null) { + result.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + } else { + Long newIssuanceDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getIssuanceDate()); + if (newIssuanceDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL); + } else { + result.setIssuanceDate(newIssuanceDate); + } + } + // Comment these lines out since we now support multi-public-keys in WeID document + // if (!WeIdUtils.validatePrivateKeyWeIdMatches( + // args.getWeIdAuthentication().getWeIdPrivateKey(), + // args.getIssuer())) { + // logger.error("Create Credential, private key does not match the current weid."); + // return new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + // } + result.setIssuer(args.getIssuer()); + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getExpirationDate()); + if (newExpirationDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + } else { + result.setExpirationDate(newExpirationDate); + } + result.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + result.addType(args.getType().getName()); + + Object claimObject = args.getClaim(); + String claimStr = null; + if (!(claimObject instanceof String)) { + claimStr = DataToolUtils.serialize(claimObject); + } else { + claimStr = (String) claimObject; + } + + HashMap claimMap = DataToolUtils.deserialize(claimStr, HashMap.class); + result.setClaim(claimMap); + + String privateKey = args.getWeIdAuthentication().getWeIdPrivateKey().getPrivateKey(); + if (StringUtils.equals(args.getType().getName(), CredentialType.LITE1.getName())) { + return createLiteCredential(result, privateKey); + } + + Map saltMap = DataToolUtils.clone(claimMap); + generateSalt(saltMap, null); + String rawData = CredentialPojoUtils + .getCredentialThumbprintWithoutSig(result, saltMap, null); + + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + result.putProofValue(ParamKeyConstant.PROOF_CREATED, result.getIssuanceDate()); + + String creator = args.getWeIdAuthentication().getWeId(); + result.putProofValue(ParamKeyConstant.PROOF_CREATOR, creator); + //TODO:目前CredentialProofType只有ECDSA类型,需要添加SM2 + String proofType = CredentialConstant.CredentialProofType.ECDSA.getTypeName(); + result.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + result.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + result.setSalt(saltMap); + ResponseData responseData = new ResponseData<>( + result, + ErrorCode.SUCCESS + ); + + return responseData; + } catch (Exception e) { + logger.error("Generate Credential failed due to system error. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); + } + } + + //创建基于hash连接的选择性披露Credential + public ResponseData createSelectiveCredential( + CredentialPojo credential, + ClaimPolicy claimPolicy) { + + if (credential == null) { + logger.error("[createSelectiveCredential] input credential is null"); + return new ResponseData(null, ErrorCode.ILLEGAL_INPUT); + } + if (credential.getType() != null + && (credential.getType().contains(CredentialType.LITE1.getName()) + || credential.getType().contains(CredentialType.ZKP.getName()))) { + logger.error( + "[createSelectiveCredential] Lite Credential and ZKP Credential DO NOT support " + + "this function(createSelectiveCredential), type = {}.", credential.getType()); + return new ResponseData(null, + ErrorCode.CREDENTIAL_NOT_SUPPORT_SELECTIVE_DISCLOSURE); + } + try { + CredentialPojo credentialClone = DataToolUtils.clone(credential); + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialClone); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return new ResponseData(null, checkResp); + } + if (credentialClone.getCptId() + .equals(CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT)) { + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + if (claimPolicy == null) { + logger.error("[createSelectiveCredential] claimPolicy is null."); + return new ResponseData(null, + ErrorCode.CREDENTIAL_CLAIM_POLICY_NOT_EXIST); + } + if (CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt())) { + return new ResponseData(null, ErrorCode.CREDENTIAL_RE_DISCLOSED); + } + String disclosure = claimPolicy.getFieldsToBeDisclosed(); + Map saltMap = credentialClone.getSalt(); + Map claim = credentialClone.getClaim(); + + Map disclosureMap = DataToolUtils + .deserialize(disclosure, HashMap.class); + + if (!validCredentialMapArgs(claim, saltMap, disclosureMap)) { + logger.error( + "[createSelectiveCredential] create failed. message is {}", + ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCodeDesc() + ); + return new ResponseData(null, + ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM); + } + // 补 policy + addKeyToPolicy(disclosureMap, claim); + // 加盐处理 + addSelectSalt(disclosureMap, saltMap, claim, false); + credentialClone.setSalt(saltMap); + + ResponseData response = new ResponseData(); + response.setResult(credentialClone); + response.setErrorCode(ErrorCode.SUCCESS); + return response; + } catch (DataTypeCastException e) { + logger.error("Generate SelectiveCredential failed, " + + "credential disclosure data type illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL); + } catch (WeIdBaseException e) { + logger.error("Generate SelectiveCredential failed, " + + "policy disclosurevalue illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL); + } catch (Exception e) { + logger.error("Generate SelectiveCredential failed due to system error. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); + } + } + + private ResponseData createLiteCredential(CredentialPojo credentialPojo, + String privateKey) { + + String rawData = CredentialPojoUtils.getLiteCredentialThumbprintWithoutSig(credentialPojo); + + // For Lite CredentialPojo, we begin to use Secp256k1 format signature to fit external type + //替换国密 + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey, 10)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + String proofType = CredentialConstant.CredentialProofType.ECDSA.getTypeName(); + credentialPojo.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + credentialPojo.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + ResponseData responseData = new ResponseData<>( + credentialPojo, + ErrorCode.SUCCESS + ); + return responseData; + } + + /** + * Salt generator. Automatically fillin the map structure in a recursive manner. + * + * @param map the passed map (claim, salt or alike) + * @param fixed fixed value if required to use + */ + public static void generateSalt(Map map, Object fixed) { + for (Map.Entry entry : map.entrySet()) { + Object value = entry.getValue(); + if (value instanceof Map) { + generateSalt((HashMap) value, fixed); + } else if (value instanceof List) { + boolean isMapOrList = generateSaltFromList((ArrayList) value, fixed); + if (!isMapOrList) { + if (fixed == null) { + addSalt(entry); + } else { + entry.setValue(fixed); + } + } + } else { + if (fixed == null) { + addSalt(entry); + } else { + entry.setValue(fixed); + } + } + } + } + + private static void addSalt(Map.Entry entry) { + String salt = DataToolUtils.getRandomSalt(); + entry.setValue(salt); + } + + private static boolean generateSaltFromList(List objList, Object fixed) { + List list = (List) objList; + for (Object obj : list) { + if (obj instanceof Map) { + generateSalt((HashMap) obj, fixed); + } else if (obj instanceof List) { + boolean result = generateSaltFromList((ArrayList) obj, fixed); + if (!result) { + return result; + } + } else { + return false; + } + } + return true; + } + + /** + * 校验claim、salt和disclosureMap的格式是否一致. + */ + private static boolean validCredentialMapArgs(Map claim, + Map salt, Map disclosureMap) { + + //检查是否为空 + if (claim == null || salt == null || disclosureMap == null) { + return false; + } + + //检查每个map里的key个数是否相同 + if (!claim.keySet().equals(salt.keySet())) { + return false; + } + + //检查key值是否一致 + for (Map.Entry entry : disclosureMap.entrySet()) { + String k = entry.getKey(); + Object v = entry.getValue(); + //如果disclosureMap中的key在claim中没有则返回false + if (!claim.containsKey(k)) { + return false; + } + Object saltV = salt.get(k); + Object claimV = claim.get(k); + if (v instanceof Map) { + //递归检查 + if (!validCredentialMapArgs((HashMap) claimV, (HashMap) saltV, (HashMap) v)) { + return false; + } + } else if (v instanceof List) { + if (!validCredentialListArgs( + (ArrayList) claimV, + (ArrayList) saltV, + (ArrayList) v + )) { + return false; + } + } + } + return true; + } + + private static boolean validCredentialListArgs( + List claimList, + List saltList, + List disclosureList) { + //检查是否为空 + if (claimList == null || saltList == null || disclosureList == null) { + return false; + } + if (claimList.size() != saltList.size()) { + return false; + } + for (int i = 0; i < disclosureList.size(); i++) { + Object disclosureObj = disclosureList.get(i); + Object claimObj = claimList.get(i); + Object saltObj = saltList.get(i); + if (disclosureObj instanceof Map) { + boolean result = + validCredentialListArgs( + claimList, + saltList, + (HashMap) disclosureObj + ); + if (!result) { + return result; + } + } else if (disclosureObj instanceof List) { + boolean result = + validCredentialListArgs( + (ArrayList) claimObj, + (ArrayList) saltObj, + (ArrayList) disclosureObj + ); + if (!result) { + return result; + } + } + } + return true; + } + + private static boolean validCredentialListArgs( + List claimList, + List saltList, + Map disclosure + ) { + + if (claimList == null || saltList == null || saltList.size() != claimList.size()) { + return false; + } + + for (int i = 0; i < claimList.size(); i++) { + Object claim = claimList.get(i); + Object salt = saltList.get(i); + boolean result = validCredentialMapArgs((HashMap) claim, (HashMap) salt, disclosure); + if (!result) { + return result; + } + } + return true; + } + + //向policy中补充缺失的key + private static void addKeyToPolicy( + Map disclosureMap, + Map claimMap + ) { + for (Map.Entry entry : claimMap.entrySet()) { + String claimK = entry.getKey(); + Object claimV = entry.getValue(); + if (claimV instanceof Map) { + HashMap claimHashMap = (HashMap) claimV; + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, new HashMap()); + } + HashMap disclosureHashMap = (HashMap) disclosureMap.get(claimK); + addKeyToPolicy(disclosureHashMap, claimHashMap); + } else if (claimV instanceof List) { + ArrayList claimList = (ArrayList) claimV; + //判断claimList中是否包含Map结构,还是单一结构 + boolean isSampleList = isSampleListForClaim(claimList); + if (isSampleList) { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, Integer.parseInt(NOT_DISCLOSED)); + } + } else { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, new ArrayList()); + } + ArrayList disclosureList = (ArrayList) disclosureMap.get(claimK); + addKeyToPolicyList(disclosureList, claimList); + } + } else { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, Integer.parseInt(NOT_DISCLOSED)); + } + } + } + } + + private static void addKeyToPolicyList( + ArrayList disclosureList, + ArrayList claimList + ) { + for (int i = 0; i < claimList.size(); i++) { + Object claimObj = claimList.get(i); + if (claimObj instanceof Map) { + Object disclosureObj = disclosureList.size() == 0 ? null : disclosureList.get(0); + if (disclosureObj == null) { + disclosureList.add(new HashMap()); + } + HashMap disclosureHashMap = (HashMap) disclosureList.get(0); + addKeyToPolicy(disclosureHashMap, (HashMap) claimObj); + break; + } else if (claimObj instanceof List) { + Object disclosureObj = disclosureList.get(i); + if (disclosureObj == null) { + disclosureList.add(new ArrayList()); + } + ArrayList disclosureArrayList = (ArrayList) disclosureList.get(i); + addKeyToPolicyList(disclosureArrayList, (ArrayList) claimObj); + } + } + } + + private static boolean isSampleListForClaim(ArrayList claimList) { + if (CollectionUtils.isEmpty(claimList)) { + return true; + } + Object claimObj = claimList.get(0); + if (claimObj instanceof Map) { + return false; + } + if (claimObj instanceof List) { + return isSampleListForClaim((ArrayList) claimObj); + } + return true; + } + + private static void addSelectSalt( + Map disclosureMap, + Map saltMap, + Map claim, + boolean isZkp + ) { + for (Map.Entry entry : disclosureMap.entrySet()) { + String disclosureKey = entry.getKey(); + Object value = entry.getValue(); + Object saltV = saltMap.get(disclosureKey); + Object claimV = claim.get(disclosureKey); + if (value == null) { + throw new WeIdBaseException(ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL); + } else if ((value instanceof Map) && (claimV instanceof Map)) { + addSelectSalt((HashMap) value, (HashMap) saltV, (HashMap) claimV, isZkp); + } else if (value instanceof List) { + addSaltForList( + (ArrayList) value, + (ArrayList) saltV, + (ArrayList) claimV, + isZkp + ); + } else { + addHashToClaim(saltMap, claim, disclosureKey, value, saltV, claimV, isZkp); + } + } + } + + private static void addHashToClaim( + Map saltMap, + Map claim, + String disclosureKey, + Object value, + Object saltV, + Object claimV, + boolean isZkp + ) { + + if (isZkp) { + if ((value instanceof Map) || !(((Integer) value).equals(Integer.parseInt(DISCLOSED)) + && claim.containsKey(disclosureKey))) { + String hash = + CredentialPojoUtils.getFieldSaltHash( + String.valueOf(claimV), + String.valueOf(saltV) + ); + claim.put(disclosureKey, hash); + } + } else { + + if (((Integer) value).equals(Integer.parseInt(NOT_DISCLOSED)) + && claim.containsKey(disclosureKey)) { + saltMap.put(disclosureKey, NOT_DISCLOSED); + String hash = + CredentialPojoUtils.getFieldSaltHash( + String.valueOf(claimV), + String.valueOf(saltV) + ); + claim.put(disclosureKey, hash); + } + } + } + + private static void addSaltForList( + List disclosures, + List salt, + List claim, + boolean isZkp) { + for (int i = 0; claim != null && i < disclosures.size(); i++) { + Object disclosureObj = disclosures.get(i); + Object claimObj = claim.get(i); + Object saltObj = salt.get(i); + if (disclosureObj instanceof Map) { + addSaltForList((HashMap) disclosureObj, salt, claim, isZkp); + } else if (disclosureObj instanceof List) { + addSaltForList( + (ArrayList) disclosureObj, + (ArrayList) saltObj, + (ArrayList) claimObj, + isZkp + ); + } + } + } + + private static void addSaltForList( + Map disclosures, + List salt, + List claim, + boolean isZkp + ) { + for (int i = 0; claim != null && i < claim.size(); i++) { + Object claimObj = claim.get(i); + Object saltObj = salt.get(i); + addSelectSalt(disclosures, (HashMap) saltObj, (HashMap) claimObj, isZkp); + } + } + + //使用提供的签发者公钥验证Credential,前提是该Credential对应的CPT文件保存在本地,如果没有请先使用registerCpt将CPT保存至本地文件 + public ResponseData verify( + String issuerPublicKey, + CredentialPojo credential) { + + if (StringUtils.isEmpty(issuerPublicKey)) { + return new ResponseData(false, ErrorCode.CREDENTIAL_PUBLIC_KEY_NOT_EXISTS); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, issuerPublicKey, null, null); + } + ErrorCode errorCode = verifyContent(credential, issuerPublicKey, credential.getCptId(), null, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + //使用提供的签发者的WeIdDocument来验证Credential,前提是该Credential对应的CPT文件保存在本地,如果没有请先使用registerCpt将CPT保存至本地文件 + public ResponseData verify(WeIdDocument weIdDocument, CredentialPojo credential) { + + if (credential == null) { + logger.error("[verify] The input credential is invalid."); + return new ResponseData(false, ErrorCode.ILLEGAL_INPUT); + } + + if (isZkpCredential(credential)) { + return verifyZkpCredential(credential); + } + + String issuerId = credential.getIssuer(); + if (!StringUtils.equals(weIdDocument.getId(), issuerId)) { + logger.error("[verify] The input issuer weid is not match the credential's."); + return new ResponseData(false, ErrorCode.CREDENTIAL_ISSUER_MISMATCH); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, null, null, weIdDocument); + } + ErrorCode errorCode = verifyContent(credential, null, credential.getCptId(), null, weIdDocument); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] credential verify failed. error message :{}", errorCode); + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + //只校验credential和cpt是否吻合 + public ResponseData> checkCredentialWithCpt( + CredentialPojo credential, + Cpt cpt + ) { + try { + if (credential == null || credential.getSalt() == null + || credential.getClaim() == null || credential.getType() == null) { + String errorMsg = ErrorCode.ILLEGAL_INPUT.getCodeDesc() + ": credential"; + logger.error("[checkCredentialWithCpt] {}.", errorMsg); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT.getCode(), errorMsg); + } + if (cpt == null || cpt.getCptJsonSchema() == null) { + String errorMsg = ErrorCode.ILLEGAL_INPUT.getCodeDesc() + ": cpt"; + logger.error("[checkCredentialWithCpt] {}.", errorMsg); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT.getCode(), errorMsg); + } + if (credential.getCptId().intValue() != cpt.getCptId().intValue()) { + logger.error("[checkCredentialWithCpt] the cptId does not match."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_CPTID_NOTMATCH); + } + // zkp不支持检查 + if (credential.getCredentialType() == CredentialType.ZKP) { + logger.error("[checkCredentialWithCpt] ZKP Credential DO NOT support."); + return new ResponseData<>(null, ErrorCode.THIS_IS_UNSUPPORTED); + } else if (credential.getCredentialType() == CredentialType.ORIGINAL) { + // 如果不是lite1类型的,则判断是否为选择性披露类型 + boolean isSelectivelyDisclosed = CredentialPojoUtils.isSelectivelyDisclosed( + credential.getSalt()); + // 如果是选择性披露 则特殊处理 + if (isSelectivelyDisclosed) { + // 做特殊处理逻辑: remove不披露的字段 并判断是否为必选字段,如果是必选字段 并且为不披露则检查失败 + credential = DataToolUtils.clone(credential); + removeDisclosedFiledMap( + credential.getClaim(), + credential.getSalt(), + cpt.getCptJsonSchema() + ); + } + } + + String cptJsonSchema = DataToolUtils.serialize(cpt.getCptJsonSchema()); + // 验证cpt自身的合法性 + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("[checkCredentialWithCpt] the cpt invalid."); + return new ResponseData<>(null, ErrorCode.CPT_JSON_SCHEMA_INVALID); + } + String claimStr = DataToolUtils.serialize(credential.getClaim()); + // 验证cpt与credential的匹配性 + Set checkRes = DataToolUtils.checkJsonVersusSchema( + claimStr, cptJsonSchema); + if (checkRes.size() != 0) { + logger.error( + "[checkCredentialWithCpt] check fail, ProcessingReport = {}.", checkRes); + ResponseData> result = new ResponseData<>( + checkRes, + ErrorCode.CREDENTIAL_DOES_NOT_MATCHE_THE_CPT + ); + return result; + } + return new ResponseData<>(checkRes, ErrorCode.SUCCESS); + } catch (WeIdBaseException e) { + logger.error("[checkCredentialWithCpt] check has base exception.", e); + return new ResponseData<>(null, e.getErrorCode().getCode(), e.getMessage()); + } catch (Exception e) { + logger.error("[checkCredentialWithCpt] check has unknown exception.", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + //计算credential的整体hash,用于给credential存证 + public ResponseData getCredentialPojoHash(CredentialPojo credentialPojo) { + ErrorCode innerResponse = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { + logger.error("Create Evidence input format error!"); + return new ResponseData<>(StringUtils.EMPTY, innerResponse); + } + return new ResponseData<>(CredentialPojoUtils.getCredentialPojoHash(credentialPojo, null), + ErrorCode.SUCCESS); + } + + private static ResponseData verifyLiteCredential( + CredentialPojo credential, + String publicKey, + String methodId, + WeIdDocument weIdDocument) { + // Lite Credential only contains limited areas (others truncated) + if (credential.getCptId() == null || credential.getCptId().intValue() < 0) { + return new ResponseData<>(false, ErrorCode.CPT_ID_ILLEGAL); + } + if (!WeIdUtils.isWeIdValid(credential.getIssuer())) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_ISSUER_INVALID); + } + if (credential.getClaim() == null || credential.getClaim().size() == 0) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS); + } + if (credential.getProof() == null || StringUtils.isEmpty(credential.getSignature())) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_SIGNATURE_NOT_EXISTS); + } + String rawData = CredentialPojoUtils.getLiteCredentialThumbprintWithoutSig(credential); + + // Using provided public key to verify signature + if (!StringUtils.isBlank(publicKey)) { + boolean result; + try { + // For Lite CredentialPojo, we begin to use Secp256k1 verify to fit external type + result = DataToolUtils.verifySignature(rawData, credential.getSignature(), new BigInteger(publicKey)); + } catch (Exception e) { + logger.error("[verifyContent] verify signature fail.", e); + return new ResponseData(false, ErrorCode.CREDENTIAL_SIGNATURE_BROKEN); + } + if (!result) { + return new ResponseData(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + if(weIdDocument != null) { + ErrorCode verifyErrorCode = DataToolUtils.verifySignatureFromWeId( + rawData, credential.getSignature(), weIdDocument, methodId); + if (verifyErrorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData(false, verifyErrorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + return new ResponseData(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); + } + + private static ErrorCode verifyContent( + CredentialPojo credential, + String publicKey, + Integer cptId, + String methodId, + WeIdDocument weIdDocument + ) { + ErrorCode errorCode; + try { + errorCode = verifyContentInner(credential, publicKey, cptId, methodId, weIdDocument); + } catch (WeIdBaseException ex) { + logger.error("[verifyContent] verify credential has exception.", ex); + return ex.getErrorCode(); + } + // System CPT business related check + if (errorCode == ErrorCode.SUCCESS + && CredentialPojoUtils.isSystemCptId(credential.getCptId())) { + errorCode = verifySystemCptClaimInner(credential); + } + return errorCode; + } + + private static ErrorCode verifySystemCptClaimInner(CredentialPojo credential) { + if (credential.getCptId().intValue() == CredentialConstant.EMBEDDED_TIMESTAMP_CPT) { + return verifyTimestampClaim(credential); + } + if (credential.getCptId().intValue() == CredentialConstant.AUTHORIZATION_CPT) { + return verifyAuthClaim(credential); + } + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyAuthClaim(CredentialPojo credential) { + Cpt101 authInfo; + try { + authInfo = DataToolUtils.mapToObj(credential.getClaim(), Cpt101.class); + } catch (Exception e) { + logger.error("Failed to deserialize authorization information."); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + ErrorCode errorCode = verifyAuthInfo(authInfo); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + // Extra check 1: cannot authorize other WeID's resources + String issuerWeId = credential.getIssuer(); + if (!issuerWeId.equalsIgnoreCase(authInfo.getFromWeId())) { + return ErrorCode.AUTHORIZATION_CANNOT_AUTHORIZE_OTHER_WEID_RESOURCE; + } + // TODO Extra check 2: check service url endpoint exposed or not? + // Need getWeIdDocument() check + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyTimestampClaim(CredentialPojo credential) { + Map claim = credential.getClaim(); + if (((String) claim.get("timestampAuthority")) + .contains(TimestampUtils.WESIGN_AUTHORITY_NAME)) { + String hashValue = (String) claim.get("claimHash"); + String authoritySignature = (String) claim.get("authoritySignature"); + Long timestamp = (long) claim.get("timestamp"); + ResponseData resp = + TimestampUtils.verifyWeSignTimestamp(hashValue, authoritySignature, timestamp); + if (!resp.getResult()) { + return ErrorCode.getTypeByErrorCode(resp.getErrorCode()); + } + } + return ErrorCode.SUCCESS; + } + + /** + * Verify the authorization info in an authorization token credential. + * + * @param authInfo the auth info in CPT101 format + * @return success if valid, specific error codes otherwise + */ + public static ErrorCode verifyAuthInfo(Cpt101 authInfo) { + if (authInfo == null) { + return ErrorCode.ILLEGAL_INPUT; + } + + String serviceUrl = authInfo.getServiceUrl(); + String resourceId = authInfo.getResourceId(); + Long duration = authInfo.getDuration(); + if (!CredentialUtils.isValidUuid(resourceId)) { + logger.error("Resource ID illegal: is not a valid UUID."); + return ErrorCode.ILLEGAL_INPUT; + } + if (!DataToolUtils.isValidEndpointUrl(serviceUrl)) { + logger.error("Service URL illegal."); + return ErrorCode.ILLEGAL_INPUT; + } + if (duration < 0) { + logger.error("Auth token duration of validity illegal: already expired."); + return ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL; + } + + String fromWeId = authInfo.getFromWeId(); + String toWeId = authInfo.getToWeId(); + if (fromWeId.equalsIgnoreCase(toWeId)) { + logger.error("FromWeId and ToWeId must be different."); + return ErrorCode.AUTHORIZATION_FROM_TO_MUST_BE_DIFFERENT; + } + /* + ResponseData existResp = getWeIdService().isWeIdExist(fromWeId); + if (!existResp.getResult()) { + logger.error("From WeID illegal: {}", existResp.getErrorMessage()); + return ErrorCode.getTypeByErrorCode(existResp.getErrorCode()); + } + existResp = getWeIdService().isWeIdExist(toWeId); + if (!existResp.getResult()) { + logger.error("To WeID illegal: {}", existResp.getErrorMessage()); + return ErrorCode.getTypeByErrorCode(existResp.getErrorCode()); + } + */ + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyContentInner( + CredentialPojo credential, + String publicKey, + Integer cptId, + String methodId, + WeIdDocument weIdDocument + ) { + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credential); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return checkResp; + } + if (credential.getCptId() == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + .intValue()) { + logger.error("Embedded Credential is obsoleted. Please use embedded Credential Pojo."); + return ErrorCode.CPT_ID_ILLEGAL; + } + if (credential.getCptId() == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT + .intValue() || credential.getCptId() == CredentialConstant.EMBEDDED_TIMESTAMP_CPT + .intValue()) { + // This is a multi-signed Credential. We firstly verify itself (i.e. external check) + ErrorCode errorCode = verifySingleSignedCredential( + credential, publicKey, cptId, methodId, weIdDocument); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + // Then, we verify its list members one-by-one + List innerCredentialList; + try { + if (credential.getClaim().get("credentialList") instanceof String) { + // For selectively-disclosed credential, stop here. External check is enough. + return ErrorCode.SUCCESS; + } else { + innerCredentialList = (ArrayList) credential.getClaim().get("credentialList"); + } + } catch (Exception e) { + logger.error("the credential claim data illegal.", e); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + for (Object innerCredentialObject : innerCredentialList) { + // PublicKey can only be used in the passed-external check, so pass-in null key + try { + CredentialPojo innerCredential; + if (!(innerCredentialObject instanceof CredentialPojo)) { + Map map = (Map) innerCredentialObject; + innerCredential = DataToolUtils + .mapToObj(map, CredentialPojo.class); + } else { + innerCredential = (CredentialPojo) innerCredentialObject; + } + errorCode = verifyContentInner( + innerCredential, null, cptId, methodId, weIdDocument); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + } catch (Exception e) { + logger.error("Failed to convert credentialPojo to object.", e); + return ErrorCode.ILLEGAL_INPUT; + } + } + return ErrorCode.SUCCESS; + } + return verifySingleSignedCredential(credential, publicKey, cptId, methodId, weIdDocument); + } + + private static ErrorCode verifySingleSignedCredential( + CredentialPojo credential, + String publicKey, + Integer cptId, + String methodId, + WeIdDocument weIdDocument + ) { + ErrorCode errorCode = verifyCptFormat( + credential.getCptId(), + credential.getClaim(), + CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt()) + ); + if (ErrorCode.SUCCESS.getCode() != errorCode.getCode()) { + return errorCode; + } + Map salt = credential.getSalt(); + String rawData; + if (CredentialPojoUtils.isEmbeddedCredential(credential)) { + List objList = (ArrayList) credential.getClaim().get("credentialList"); + List credentialList = new ArrayList<>(); + try { + for (Object obj : objList) { + if (obj instanceof CredentialPojo) { + credentialList.add((CredentialPojo) obj); + } else { + credentialList.add(DataToolUtils + .mapToObj((HashMap) obj, CredentialPojo.class)); + } + } + } catch (Exception e) { + logger.error("Failed to convert credentialPojo: " + e.getMessage(), e); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + rawData = CredentialPojoUtils.getEmbeddedCredentialThumbprintWithoutSig(credentialList); + } else { + rawData = CredentialPojoUtils + .getCredentialThumbprintWithoutSig(credential, salt, null); + } + String issuerWeid = credential.getIssuer(); + if (!StringUtils.isEmpty(publicKey)) { + boolean result; + try { + result = DataToolUtils.verifySignature(rawData, + credential.getSignature(), new BigInteger(publicKey)); + + } catch (Exception e) { + logger.error("[verifyContent] verify signature fail.", e); + return ErrorCode.CREDENTIAL_SIGNATURE_BROKEN; + } + if (!result) { + return ErrorCode.CREDENTIAL_VERIFY_FAIL; + } + return ErrorCode.SUCCESS; + } else if (weIdDocument != null) { + errorCode = DataToolUtils.verifySignatureFromWeId( + rawData, credential.getSignature(), weIdDocument, methodId); + return errorCode; + } + return ErrorCode.CREDENTIAL_VERIFY_FAIL; + } + + private static ErrorCode verifyCptFormat( + Integer cptId, Map claim, + boolean isSelectivelyDisclosed + ) { + if (cptId == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT.intValue()) { + if (!claim.containsKey("credentialList")) { + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } else { + return ErrorCode.SUCCESS; + } + } + if (cptId == CredentialConstant.EMBEDDED_TIMESTAMP_CPT.intValue()) { + if (claim.containsKey("credentialList") && claim.containsKey("claimHash") + && claim.containsKey("timestampAuthority") && claim.containsKey("timestamp") + && claim.containsKey("authoritySignature")) { + return ErrorCode.SUCCESS; + } else { + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + } + try { + /*if (offline) { + return ErrorCode.SUCCESS; + }*/ + String claimStr = DataToolUtils.serialize(claim); + //Cpt cpt = getCptService().queryCpt(cptId).getResult(); + Cpt cpt = weIdServiceConsole.queryCpt(cptId).getResult(); + if (cpt == null) { + logger.error(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCodeDesc()); + return ErrorCode.CREDENTIAL_CPT_NOT_EXISTS; + } + //String cptJsonSchema = JsonUtil.objToJsonStr(cpt.getCptJsonSchema()); + String cptJsonSchema = DataToolUtils.serialize(cpt.getCptJsonSchema()); + + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCodeDesc()); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + if (!isSelectivelyDisclosed) { + Set checkRes = DataToolUtils.checkJsonVersusSchema( + claimStr, cptJsonSchema); + if (checkRes.size() != 0) { + logger.error(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCodeDesc()); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + } + return ErrorCode.SUCCESS; + } catch (Exception e) { + logger.error( + "Generic error occurred during verify cpt format when verifyCredential: ", e); + return ErrorCode.CREDENTIAL_ERROR; + } + } + + private static Boolean isZkpCredential(CredentialPojo credential) { + + List types = credential.getType(); + for (String type : types) { + if (StringUtils.equals(type, CredentialType.ZKP.getName())) { + return true; + } + } + return false; + } + + private static ResponseData verifyZkpCredential(CredentialPojo credential) { + + Map proof = credential.getProof(); + String encodedVerificationRule = (String) proof + .get(ParamKeyConstant.PROOF_ENCODEDVERIFICATIONRULE); + String verificationRequest = (String) proof.get(ParamKeyConstant.PROOF_VERIFICATIONREQUEST); + VerifierResult verifierResult = + VerifierClient.verifyProof(encodedVerificationRule, verificationRequest); + if (verifierResult.wedprErrorMessage == null) { + return new ResponseData(true, ErrorCode.SUCCESS); + } + + return new ResponseData(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); + } + + // 移除不披露的字段 + private void removeDisclosedFiledMap( + Map claim, + Map salt, + Map properties + ) { + ArrayList requireds = (ArrayList)properties.get("required"); + Map nextProperties = (Map)properties.get("properties"); + // 遍历claim + for (Map.Entry entry : salt.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof Map) { + // 说明下一层为map + removeDisclosedFiledMap( + (Map) claim.get(key), + (Map) value, + (Map) nextProperties.get(key) + ); + } else if (value instanceof List) { + // 说明下一层是List + removeDisclosedFiledList( + (ArrayList) claim.get(key), + (ArrayList) value, + (Map) nextProperties.get(key)); + } else { + // 说明当前层为需要处理的层 + // 如果当前为不披露的key + // 1. 如果必须的key则报错 + // 2. 否则移除此key + if ("0".equals(value.toString())) { + // 说明是选择性披露 + if (requireds != null && requireds.contains(key)) { + throw new WeIdBaseException(key + " is required and disclosed."); + } else { + claim.remove(key); + } + } + } + } + } + + private void removeDisclosedFiledList( + ArrayList claims, + ArrayList salts, + Map properties + ) { + for (int i = 0; i < claims.size(); i++) { + Object claim = claims.get(i); + if (claim instanceof Map) { + removeDisclosedFiledMap( + (Map) claim, + (Map) salts.get(i), + (Map) properties.get("items") + ); + } else { + removeDisclosedFiledList( + (ArrayList) claim, + (ArrayList) salts.get(i), + (Map) properties.get("items") + ); + } + } + } + +} diff --git a/src/main/java/com/webank/weid/service/console/WeIdServiceConsole.java b/src/main/java/com/webank/weid/service/console/WeIdServiceConsole.java new file mode 100644 index 00000000..e9eb1e6f --- /dev/null +++ b/src/main/java/com/webank/weid/service/console/WeIdServiceConsole.java @@ -0,0 +1,682 @@ + + +package com.webank.weid.service.console; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.webank.wedpr.selectivedisclosure.CredentialTemplateEntity; +import com.webank.wedpr.selectivedisclosure.IssuerClient; +import com.webank.wedpr.selectivedisclosure.IssuerResult; +import com.webank.wedpr.selectivedisclosure.proto.AttributeTemplate; +import com.webank.wedpr.selectivedisclosure.proto.TemplatePublicKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.CptType; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.protocol.response.RsvSignature; +import com.webank.weid.suite.cache.CacheManager; +import com.webank.weid.suite.cache.CacheNode; +import com.webank.weid.util.*; +import com.webank.weid.util.Multibase.Multibase; +import com.webank.weid.util.Multicodec.Multicodec; +import com.webank.weid.util.Multicodec.MulticodecEncoder; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.fisco.bcos.sdk.model.CryptoType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * Service implementations for operations on WeIdentity DID. + * + * @author afeexian 2023.06 + */ +public class WeIdServiceConsole { + + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(WeIdServiceConsole.class); + + private static int CPT_DEFAULT_VERSION = 1; + + //获取CPT缓存节点 + private static CacheNode> cptCahceNode = + CacheManager.registerCacheNode("SYS_CPT", 1000 * 3600 * 24L); + + /** + * Create a WeIdentity DID Document. + * @param publicKey the publicKey + * @return the WeIdDocument + */ + public ResponseData createWeIdDocument(String publicKey) { + if (StringUtils.isNotBlank(publicKey)) { + String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //在创建weid时默认添加一个id为#keys-[hash(publicKey)]的verification method + authenticationProperty.setId(weId + "#keys-" + DataToolUtils.hash(publicKey).substring(58)); + //verification method controller默认为自己 + authenticationProperty.setController(weId); + //这里把publicKey用multicodec编码,然后使用Multibase格式化,国密和非国密使用不同的编码 + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + publicKey.getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + List authList = new ArrayList<>(); + authList.add(authenticationProperty); + List serviceList = new ArrayList<>(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setServiceEndpoint("https://github.com/WeBankBlockchain/WeIdentity"); + serviceProperty.setType("WeIdentity"); + serviceProperty.setId(authenticationProperty.getController() + '#' + DataToolUtils.hash(serviceProperty.getServiceEndpoint()).substring(58)); + serviceList.add(serviceProperty); + WeIdDocument weIdDocument = new WeIdDocument(); + weIdDocument.setId(weId); + weIdDocument.setService(serviceList); + weIdDocument.setAuthentication(authList); + return new ResponseData<>(weIdDocument, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, ErrorCode.WEID_PUBLICKEY_INVALID); + } + } + + /** + * Create a WeIdentity DID DocumentMetadata. + * + * @return the WeIdDocumentMetadata + */ + public ResponseData createWeIdDocumentMetadata() { + WeIdDocumentMetadata weIdDocumentMetadata = new WeIdDocumentMetadata(); + weIdDocumentMetadata.setCreated(DateUtils.getNoMillisecondTimeStamp()); + weIdDocumentMetadata.setDeactivated(false); + weIdDocumentMetadata.setUpdated(DateUtils.getNoMillisecondTimeStamp()); + weIdDocumentMetadata.setVersionId(1); + return new ResponseData<>(weIdDocumentMetadata, ErrorCode.SUCCESS); + } + + /** + * Create a WeIdentity DID Document Json. + * @param publicKey the publicKey + * @return the WeIdentity DID document json + */ + public ResponseData createWeIdDocumentJson(String publicKey) { + + ResponseData responseData = this.createWeIdDocument(publicKey); + WeIdDocument result = responseData.getResult(); + + if (result == null) { + return new ResponseData<>( + StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(responseData.getErrorCode()) + ); + } + ObjectMapper mapper = new ObjectMapper(); + String weIdDocument; + try { + weIdDocument = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result); + } catch (Exception e) { + logger.error("write object to String fail.", e); + return new ResponseData<>( + StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(responseData.getErrorCode()) + ); + } + weIdDocument = + new StringBuffer() + .append(weIdDocument) + .insert(1, WeIdConstant.WEID_DOC_PROTOCOL_VERSION) + .toString(); + + ResponseData responseDataJson = new ResponseData(); + responseDataJson.setResult(weIdDocument); + responseDataJson.setErrorCode(ErrorCode.getTypeByErrorCode(responseData.getErrorCode())); + + return responseDataJson; + } + + /** + * Set authentications in WeIdentity DID. + * + * @param weIdDocument the weIdDocument to set auth to + * @param authenticationArgs A public key is needed + * @return true if the "set" operation succeeds, false otherwise. + */ + public ResponseData setAuthentication( + WeIdDocument weIdDocument, + AuthenticationArgs authenticationArgs){ + + if (!verifyAuthenticationArgs(authenticationArgs)) { + logger.error("[setAuthentication]: input parameter setAuthenticationArgs is illegal."); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + return processSetAuthentication( + authenticationArgs, + weIdDocument); + } + + private ResponseData processSetAuthentication( + AuthenticationArgs authenticationArgs, + WeIdDocument weIdDocument) { + String weId = weIdDocument.getId(); + if (WeIdUtils.isWeIdValid(weId)) { + //检查authentication的controller WeId是否存在和是否被注销 + if (StringUtils.isEmpty(authenticationArgs.getController())) { + authenticationArgs.setController(weId); + } + if (!WeIdUtils.isWeIdValid(authenticationArgs.getController())) { + logger.error("[setAuthentication]: controller : {} is invalid.", authenticationArgs.getController()); + return new ResponseData<>(null, ErrorCode.WEID_INVALID); + } + for(int i=0; i(null, ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS); + } + if(!StringUtils.isEmpty(authenticationArgs.getId()) && authenticationArgs.getId().equals(weIdDocument.getAuthentication().get(i).getId())){ + logger.error("[setAuthentication]: failed, the Authentication with id :{} exists", + authenticationArgs.getId()); + return new ResponseData<>(null, ErrorCode.AUTHENTICATION_METHOD_ID_EXISTS); + } + } + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //如果用户没有指定method id,则系统分配 + authenticationProperty.setId(authenticationArgs.getId()); + if(StringUtils.isBlank(authenticationArgs.getId())){ + authenticationProperty.setId(weId + "#keys-" + DataToolUtils.hash(authenticationArgs.getPublicKey()).substring(58)); + } + authenticationProperty.setController(authenticationArgs.getController()); + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + authenticationArgs.getPublicKey().getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + + List authentication = weIdDocument.getAuthentication(); + authentication.add(authenticationProperty); + weIdDocument.setAuthentication(authentication); + return new ResponseData<>(weIdDocument, ErrorCode.SUCCESS); + } else { + logger.error("Set authenticate failed. weid : {} is invalid.", weId); + return new ResponseData<>(null, ErrorCode.WEID_INVALID); + } + } + + private boolean verifyAuthenticationArgs(AuthenticationArgs authenticationArgs) { + + return !(authenticationArgs == null + || StringUtils.isEmpty(authenticationArgs.getPublicKey()) + || !(isPublicKeyStringValid(authenticationArgs.getPublicKey()))); + } + + private boolean isPublicKeyStringValid(String pubKey) { + // Allow base64, rsa (alphaNum) and bigInt + return (DataToolUtils.isValidBase64String(pubKey) + // || StringUtils.isAlphanumeric(pubKey) + || NumberUtils.isDigits(pubKey)); + } + + /** + * Set service properties. + * + * @param weIdDocument the weIdDocument to set service to + * @param serviceArgs your service name and endpoint + * @return true if the "set" operation succeeds, false otherwise. + */ + public ResponseData setService(WeIdDocument weIdDocument, ServiceArgs serviceArgs) { + if (!verifyServiceArgs(serviceArgs)) { + logger.error("[setService]: input parameter setServiceArgs is illegal."); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + return processSetService( + weIdDocument, + serviceArgs); + + } + + private ResponseData processSetService( + WeIdDocument weIdDocument, + ServiceArgs serviceArgs) { + String weId = weIdDocument.getId(); + if (WeIdUtils.isWeIdValid(weId)) { + List service = weIdDocument.getService(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setType(serviceArgs.getType()); + serviceProperty.setServiceEndpoint(serviceArgs.getServiceEndpoint()); + if(weIdDocument.getService().size()==0){ + if(StringUtils.isEmpty(serviceArgs.getId())){ + serviceProperty.setId(weId + '#' + DataToolUtils.hash(serviceArgs.getServiceEndpoint())); + }else{ + serviceProperty.setId(serviceArgs.getId()); + } + }else{ + if(StringUtils.isEmpty(serviceArgs.getId())){ + serviceProperty.setId(weId + '#' + DataToolUtils.hash(serviceArgs.getServiceEndpoint()).substring(58)); + }else{ + for(int i=0; i(null, ErrorCode.SERVICE_METHOD_ID_EXISTS); + } + } + serviceProperty.setId(serviceArgs.getId()); + } + } + service.add(serviceProperty); + weIdDocument.setService(service); + return new ResponseData<>(weIdDocument, ErrorCode.SUCCESS); + } else { + logger.error("[setService] set service failed, weid -->{} is invalid.", weId); + return new ResponseData<>(null, ErrorCode.WEID_INVALID); + } + } + + private boolean verifyServiceArgs(ServiceArgs serviceArgs) { + + return !(serviceArgs == null + || StringUtils.isBlank(serviceArgs.getType()) + || StringUtils.isBlank(serviceArgs.getServiceEndpoint())); + } + + /** + * Save a new CPT with a pre-set CPT ID, to the local file. + * + * @param args the args + * @param cptId the CPT ID + * @return response data + */ + public ResponseData registerCpt(CptMapArgs args, Integer cptId) { + if (args == null || cptId == null || cptId <= 0) { + logger.error("[registerCpt] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + try { + ErrorCode errorCode = + this.validateCptArgs( + args.getWeIdAuthentication(), + args.getCptJsonSchema() + ); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + + String weId = args.getWeIdAuthentication().getWeId(); + WeIdPrivateKey weIdPrivateKey = args.getWeIdAuthentication().getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); + RsvSignature rsvSignature = sign( + weId, + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + Cpt cpt = new Cpt(); + cpt.setCptId(cptId); + cpt.setCreated(DateUtils.getNoMillisecondTimeStamp()); + cpt.setUpdated(DateUtils.getNoMillisecondTimeStamp()); + cpt.setCptVersion(CPT_DEFAULT_VERSION); + cpt.setCptPublisher(address); + cpt.setCptJsonSchema(args.getCptJsonSchema()); + cpt.setCptSignature(DataToolUtils.SigBase64Serialization(rsvSignature)); + + //单机模式不需要提前存储ZKP Template,需要用的时候再生成 + //ErrorCode errorCodeProcess = processTemplate(cptId, cptJsonSchemaNew); + //把cpt保存到本地文件,名字为:Cpt[cptId] + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Cpt"+cptId); + // if file does not exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + mapper.writeValue(file, cpt); + + CptBaseInfo cptBaseInfo = new CptBaseInfo(); + cptBaseInfo.setCptId(cptId); + cptBaseInfo.setCptVersion(CPT_DEFAULT_VERSION); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS); + /*return cptServiceEngine.registerCpt(cptId, address, cptJsonSchemaNew, rsvSignature, + weIdPrivateKey.getPrivateKey(), WeIdConstant.CPT_DATA_INDEX);*/ + + } catch (Exception e) { + logger.error("[registerCpt] register cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * this is used to query cpt with the latest version which has been saved. + * + * @param cptId the cpt id + * @return the response data + */ + public ResponseData queryCpt(Integer cptId) { + + try { + if (cptId == null || cptId < 0) { + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + String cptIdStr = String.valueOf(cptId); + ResponseData result = cptCahceNode.get(cptIdStr); + if (result == null) { + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Cpt"+cptId); + // if file does not exists, then create it + if (!file.exists()) { + logger.error("[queryCpt] cpt file not exist in local"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + Cpt cpt = mapper.readValue(file, Cpt.class); + cptCahceNode.put(cptIdStr, new ResponseData<>(cpt, ErrorCode.SUCCESS)); + return new ResponseData<>(cpt, ErrorCode.SUCCESS); + /*result = cptServiceEngine.queryCpt(cptId, WeIdConstant.CPT_DATA_INDEX); + if (result.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) { + cptCahceNode.put(cptIdStr, result); + }*/ + } + return result; + } catch (Exception e) { + logger.error("[updateCpt] query cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * This is used to update a CPT data which has been register. + * + * @param args the args + * @param cptId the cptId + * @return the response data + */ + public ResponseData updateCpt(CptMapArgs args, Integer cptId) { + + try { + if (args == null) { + logger.error("[updateCpt]input UpdateCptArgs is null"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + if (cptId == null || cptId.intValue() < 0) { + logger.error("[updateCpt]input cptId illegal"); + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + ErrorCode errorCode = + this.validateCptArgs( + args.getWeIdAuthentication(), + args.getCptJsonSchema() + ); + + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + + String weId = args.getWeIdAuthentication().getWeId(); + WeIdPrivateKey weIdPrivateKey = args.getWeIdAuthentication().getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); + RsvSignature rsvSignature = sign( + weId, + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Cpt"+cptId); + // if file does not exists, then create it + if (!file.exists()) { + logger.error("[queryCpt] cpt file not exist in local"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + Cpt cpt = mapper.readValue(file, Cpt.class); + cpt.setCptPublisher(address); + cpt.setCptJsonSchema(args.getCptJsonSchema()); + cpt.setCptSignature(DataToolUtils.SigBase64Serialization(rsvSignature)); + cpt.setCptVersion(cpt.getCptVersion() + 1); + cpt.setUpdated(DateUtils.getNoMillisecondTimeStamp()); + mapper.writeValue(file, cpt); + + cptCahceNode.remove(String.valueOf(cptId)); + CptBaseInfo cptBaseInfo = new CptBaseInfo(); + cptBaseInfo.setCptId(cptId); + cptBaseInfo.setCptVersion(cpt.getCptVersion()); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[updateCpt] update cpt failed due to unkown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CptService#queryCredentialTemplate(java.lang.Integer) + */ + public ResponseData queryCredentialTemplate(Integer cptId) { + Cpt cpt = queryCpt(cptId).getResult(); + CptMapArgs args = new CptMapArgs(); + args.setCptType(CptType.ZKP); + args.setCptJsonSchema(cpt.getCptJsonSchema()); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); + List attributeList; + try { + attributeList = JsonUtil.extractCptProperties(cptJsonSchemaNew); + IssuerResult issuerResult = IssuerClient.makeCredentialTemplate(attributeList); + CredentialTemplateEntity template = issuerResult.credentialTemplateEntity; + String templateSecretKey = issuerResult.templateSecretKey; + CredentialTemplateEntity credentialTemplateEntity = new CredentialTemplateEntity(); + TemplatePublicKey pubKey = TemplatePublicKey.newBuilder().setCredentialPublicKey(template.getPublicKey().getCredentialPublicKey()).build(); + credentialTemplateEntity.setPublicKey(pubKey); + credentialTemplateEntity.setCredentialKeyCorrectnessProof(template.getCredentialKeyCorrectnessProof()); + List attrList; + attrList = JsonUtil.extractCptProperties(cpt.getCptJsonSchema()); + AttributeTemplate.Builder builder = AttributeTemplate.newBuilder(); + for (String attr : attrList) { + builder.addAttributeKey(attr); + } + AttributeTemplate attributes = builder.build(); + credentialTemplateEntity.setCredentialSchema(attributes); + return new ResponseData<>(credentialTemplateEntity, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[processTemplate] process credential template failed.", e); + return new ResponseData<>(null, ErrorCode.CPT_CREDENTIAL_TEMPLATE_SAVE_ERROR); + } + } + + private ErrorCode validateCptArgs( + WeIdAuthentication weIdAuthentication, + Map cptJsonSchemaMap) throws Exception { + + if (weIdAuthentication == null) { + logger.error("Input cpt weIdAuthentication is invalid."); + return ErrorCode.WEID_AUTHORITY_INVALID; + } + + String weId = weIdAuthentication.getWeId(); + if (!WeIdUtils.isWeIdValid(weId)) { + logger.error("Input cpt publisher : {} is invalid.", weId); + return ErrorCode.WEID_INVALID; + } + + ErrorCode errorCode = validateCptJsonSchemaMap(cptJsonSchemaMap); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return errorCode; + } + String cptJsonSchema = DataToolUtils.serialize(cptJsonSchemaMap); + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("Input cpt json schema : {} is invalid.", cptJsonSchemaMap); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + WeIdPrivateKey weIdPrivateKey = weIdAuthentication.getWeIdPrivateKey(); + if (weIdPrivateKey == null + || StringUtils.isEmpty(weIdPrivateKey.getPrivateKey())) { + logger.error( + "Input cpt publisher private key : {} is in valid.", + weIdPrivateKey + ); + return ErrorCode.WEID_PRIVATEKEY_INVALID; + } + + if (!WeIdUtils.validatePrivateKeyWeIdMatches(weIdPrivateKey, weId)) { + return ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH; + } + return ErrorCode.SUCCESS; + } + + private ErrorCode validateCptJsonSchemaMap( + Map cptJsonSchemaMap) throws Exception { + if (cptJsonSchemaMap == null || cptJsonSchemaMap.isEmpty()) { + logger.error("Input cpt json schema is invalid."); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + //String cptJsonSchema = JsonUtil.objToJsonStr(cptJsonSchemaMap); + String cptJsonSchema = DataToolUtils.serialize(cptJsonSchemaMap); + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("Input cpt json schema : {} is invalid.", cptJsonSchemaMap); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + return ErrorCode.SUCCESS; + } + + private RsvSignature sign( + String cptPublisher, + String jsonSchema, + WeIdPrivateKey cptPublisherPrivateKey) { + + StringBuilder sb = new StringBuilder(); + sb.append(cptPublisher); + sb.append(WeIdConstant.PIPELINE); + sb.append(jsonSchema); + return DataToolUtils.signToRsvSignature( + sb.toString(), cptPublisherPrivateKey.getPrivateKey()); + } + + /** + * Save a new Policy with a random Policy ID, to the local file. + * + * @param policyJson the policyJson + * @param auth the WeIdAuthentication + * @return response data + */ + public ResponseData registerPolicy(String policyJson, WeIdAuthentication auth) { + if (!DataToolUtils.isValidJsonStr(policyJson)) { + logger.error("[registerPolicy] input json format illegal."); + return new ResponseData<>(-1, ErrorCode.CPT_JSON_SCHEMA_INVALID); + } + ErrorCode errorCode = CredentialPojoUtils.isWeIdAuthenticationValid(auth); + if (errorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(-1, errorCode); + } + try { + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(auth); + Map cptJsonSchemaMap = DataToolUtils.deserialize(policyJson, HashMap.class); + cptMapArgs.setCptJsonSchema(cptJsonSchemaMap); + WeIdPrivateKey weIdPrivateKey = auth.getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.serialize(cptMapArgs.getCptJsonSchema()); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed(cptJsonSchemaNew); + //把policy保存到本地文件,名字为:Policy[policyId] + Integer policyId = new Random().nextInt(100); + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Policy"+policyId); + // if file does not exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + mapper.writeValue(file, claimPolicy); + return new ResponseData<>(policyId, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[registerPolicyData] register policy failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * Get Claim Policy Json from local file given a policy ID. + * + * @param policyId the Claim Policy ID + * @return the claim Json + */ + public ResponseData getClaimPolicy(Integer policyId) { + try { + if (policyId == null || policyId < 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Policy"+policyId); + // if file does not exists, then create it + if (!file.exists()) { + logger.error("[getClaimPolicy] policy file not exist in local"); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_CLAIM_POLICY_NOT_EXIST); + } + ClaimPolicy claimPolicy = mapper.readValue(file, ClaimPolicy.class); + return new ResponseData<>(claimPolicy, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[getClaimPolicy] query policy failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * Register Presentation Policy which contains a number of claim policies. + * + * @param claimPolicyIdList claim policies list + * @param weIdAuthentication weid auth + * @return the presentation policy id + */ + public ResponseData registerPresentationPolicy(List claimPolicyIdList, + WeIdAuthentication weIdAuthentication) { + ErrorCode errorCode = CredentialPojoUtils.isWeIdAuthenticationValid(weIdAuthentication); + if (errorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(-1, errorCode); + } + try { + int presentationPolicyId = new Random().nextInt(100); + PresentationPolicyE presentationPolicyE = new PresentationPolicyE(); + Map policyMap = new HashMap<>(); + for (Integer id : claimPolicyIdList) { + policyMap.put(id, getClaimPolicy(id).getResult()); + } + presentationPolicyE.setId(presentationPolicyId); + presentationPolicyE.setPolicyPublisherWeId(WeIdUtils.getWeIdFromPrivateKey(weIdAuthentication.getWeIdPrivateKey().getPrivateKey())); + presentationPolicyE.setPolicy(policyMap); + //把Presentation policy保存到本地文件,名字为:Presentation[presentationId] + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Presentation"+presentationPolicyId); + // if file does not exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + mapper.writeValue(file, presentationPolicyE); + return new ResponseData<>(presentationPolicyId, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[registerPresentationPolicy] register Presentation failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * Get Presentation policies under this id from local file. + * + * @param presentationPolicyId presentation policy id + * @return the full presentation policy + */ + public ResponseData getPresentationPolicy(Integer presentationPolicyId) { + if (presentationPolicyId == null || presentationPolicyId < 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + try { + ObjectMapper mapper = new ObjectMapper(); + File file = new File("Presentation"+presentationPolicyId); + // if file does not exists, then create it + if (!file.exists()) { + logger.error("[getPresentationPolicy] Presentation policy file not exist in local"); + return new ResponseData<>(null, ErrorCode.POLICY_SERVICE_NOT_EXISTS); + } + PresentationPolicyE presentationPolicyE = mapper.readValue(file, PresentationPolicyE.class); + return new ResponseData<>(presentationPolicyE, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[getPresentationPolicy] query Presentation policy failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + +} diff --git a/src/main/java/com/webank/weid/service/impl/AuthorityIssuerServiceImpl.java b/src/main/java/com/webank/weid/service/impl/AuthorityIssuerServiceImpl.java index 8055e914..ceaf7071 100644 --- a/src/main/java/com/webank/weid/service/impl/AuthorityIssuerServiceImpl.java +++ b/src/main/java/com/webank/weid/service/impl/AuthorityIssuerServiceImpl.java @@ -1,58 +1,32 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.service.impl; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import com.webank.weid.service.local.AuthorityIssuerServiceLocal; +import com.webank.weid.service.local.CptServiceLocal; +import com.webank.weid.service.local.PolicyServiceLocal; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import com.webank.weid.config.ContractConfig; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; import com.webank.weid.constant.WeIdConstant; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.contract.AuthorityIssuerController.AuthorityIssuerRetLogEventResponse; import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.IssuerType; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.AuthorityIssuerService; -import com.webank.weid.rpc.WeIdService; -import com.webank.weid.service.BaseService; -import com.webank.weid.util.DataTypetUtils; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.rpc.AuthorityIssuerService; +import com.webank.weid.service.rpc.WeIdService; import com.webank.weid.util.WeIdUtils; /** @@ -60,43 +34,30 @@ * * @author chaoxinhu 2018.10 */ -@Component -public class AuthorityIssuerServiceImpl extends BaseService implements AuthorityIssuerService { +public class AuthorityIssuerServiceImpl implements AuthorityIssuerService { - private static final Logger logger = LoggerFactory.getLogger(AuthorityIssuerServiceImpl.class); + private static final Logger logger = LoggerFactory + .getLogger(AuthorityIssuerServiceImpl.class); + private static com.webank.weid.blockchain.rpc.AuthorityIssuerService authorityBlockchainService; - private static AuthorityIssuerController authorityIssuerController; - private static String authorityIssuerControllerAddress; + private WeIdService weIdService = new WeIdServiceImpl(); - @Autowired - private WeIdService weIdService; - - /** - * Instantiates a new authority issuer service impl. - */ - public AuthorityIssuerServiceImpl() { - init(); + public AuthorityIssuerServiceImpl(){ + authorityBlockchainService = getAuthorityIssuerService(); } - private static void init() { - ContractConfig config = context.getBean(ContractConfig.class); - authorityIssuerController = - (AuthorityIssuerController) - getContractService(config.getIssuerAddress(), AuthorityIssuerController.class); - authorityIssuerControllerAddress = config.getIssuerAddress(); - } - - /** - * Use the cpt publisher's private key to send the transaction to call the contract. - * - * @param privateKey the private key - */ - private static void reloadContract(String privateKey) { - authorityIssuerController = (AuthorityIssuerController) reloadContract( - authorityIssuerControllerAddress, - privateKey, - AuthorityIssuerController.class - ); + private static com.webank.weid.blockchain.rpc.AuthorityIssuerService getAuthorityIssuerService() { + if(authorityBlockchainService != null) { + return authorityBlockchainService; + } else { + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("blockchain")) { + return new com.webank.weid.blockchain.service.impl.AuthorityIssuerServiceImpl(); + } else { + // default database + return new AuthorityIssuerServiceLocal(); + } + } } /** @@ -107,60 +68,24 @@ private static void reloadContract(String privateKey) { */ @Override public ResponseData registerAuthorityIssuer(RegisterAuthorityIssuerArgs args) { - ResponseData responseData = new ResponseData(); - ResponseData innerResponseData = checkRegisterAuthorityIssuerArgs(args); - if (!innerResponseData.getResult()) { - return new ResponseData<>( - false, innerResponseData.getErrorCode(), innerResponseData.getErrorMessage()); - } - - AuthorityIssuer authorityIssuer = args.getAuthorityIssuer(); - String weAddress = WeIdUtils.convertWeIdToAddress(authorityIssuer.getWeId()); - String[] stringAttributes = loadNameToStringAttributes(authorityIssuer.getName()); - long[] longAttributes = new long[16]; - Long createDate = System.currentTimeMillis(); - longAttributes[0] = createDate; - DynamicBytes accValue = new DynamicBytes(authorityIssuer.getAccValue().getBytes()); - Address addr = new Address(weAddress); + ErrorCode innerResponseData = checkRegisterAuthorityIssuerArgs(args); + if (ErrorCode.SUCCESS.getCode() != innerResponseData.getCode()) { + return new ResponseData<>(false, innerResponseData); + } try { - reloadContract(args.getWeIdPrivateKey().getPrivateKey()); - Future future = authorityIssuerController.addAuthorityIssuer( - addr, - DataTypetUtils.stringArrayToBytes32StaticArray(stringAttributes), - DataTypetUtils.longArrayToInt256StaticArray(longAttributes), - accValue - ); - TransactionReceipt receipt = future.get( - WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, - TimeUnit.SECONDS - ); - List eventList = - AuthorityIssuerController.getAuthorityIssuerRetLogEvents(receipt); - - AuthorityIssuerRetLogEventResponse event = eventList.get(0); - if (event != null) { - responseData = verifyAuthorityIssuerRelatedEvent( - event, - addr, - WeIdConstant.ADD_AUTHORITY_ISSUER_OPCODE - ); - } else { - logger.error( - "register authority issuer failed due to transcation event decoding failure."); - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.addAuthorityIssuer(RegisterAuthorityIssuerArgs.toBlockChain(args)); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); } - } catch (TimeoutException e) { - logger.error("register authority issuer failed due to system timeout. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); - } catch (InterruptedException | ExecutionException e) { - logger.error("register authority issuer failed due to transaction error. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.addAuthorityIssuer(args); } catch (Exception e) { - logger.error("register authority issuer failed.", e); + logger.error("register has error, Error Message:{}", e); return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); } - return responseData; } /** @@ -171,50 +96,24 @@ public ResponseData registerAuthorityIssuer(RegisterAuthorityIssuerArgs */ @Override public ResponseData removeAuthorityIssuer(RemoveAuthorityIssuerArgs args) { - ResponseData responseData = new ResponseData(); - ResponseData innerResponseData = checkRemoveAuthorityIssuerArgs(args); - if (!innerResponseData.getResult()) { - return new ResponseData<>( - false, - innerResponseData.getErrorCode(), - innerResponseData.getErrorMessage() - ); + ErrorCode innerResponseData = checkRemoveAuthorityIssuerArgs(args); + if (ErrorCode.SUCCESS.getCode() != innerResponseData.getCode()) { + return new ResponseData<>(false, innerResponseData); } - - String weId = args.getWeId(); - Address addr = new Address(WeIdUtils.convertWeIdToAddress(weId)); try { - reloadContract(args.getWeIdPrivateKey().getPrivateKey()); - Future future = authorityIssuerController - .removeAuthorityIssuer(addr); - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List eventList = - AuthorityIssuerController.getAuthorityIssuerRetLogEvents(receipt); - - AuthorityIssuerRetLogEventResponse event = eventList.get(0); - if (event != null) { - responseData = verifyAuthorityIssuerRelatedEvent( - event, - addr, - WeIdConstant.REMOVE_AUTHORITY_ISSUER_OPCODE - ); - } else { - logger.error("remove authority issuer failed, transcation event decoding failure."); - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.removeAuthorityIssuer(args.getWeId(), args.getWeIdPrivateKey().getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); } - } catch (TimeoutException e) { - logger.error("remove authority issuer failed due to system timeout. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); - } catch (InterruptedException | ExecutionException e) { - logger.error("remove authority issuer failed due to transaction error. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.removeAuthorityIssuer(args); } catch (Exception e) { logger.error("remove authority issuer failed.", e); return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); } - return responseData; } /** @@ -225,37 +124,91 @@ public ResponseData removeAuthorityIssuer(RemoveAuthorityIssuerArgs arg */ @Override public ResponseData isAuthorityIssuer(String weId) { - ResponseData responseData = new ResponseData(); if (!WeIdUtils.isWeIdValid(weId)) { return new ResponseData<>(false, ErrorCode.WEID_INVALID); } - Address addr = new Address(WeIdUtils.convertWeIdToAddress(weId)); + String addr = WeIdUtils.convertWeIdToAddress(weId); try { - Future future = authorityIssuerController.isAuthorityIssuer(addr); - Boolean result = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS).getValue(); - responseData.setResult(result); - if (result) { - responseData.setErrorCode(ErrorCode.SUCCESS.getCode()); - responseData.setErrorMessage(ErrorCode.SUCCESS.getCodeDesc()); - } else { - responseData - .setErrorCode(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode()); - responseData.setErrorMessage( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCodeDesc()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.isAuthorityIssuer(addr); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); } - } catch (TimeoutException e) { - logger.error("check authority issuer id failed due to system timeout. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); - } catch (InterruptedException | ExecutionException e) { - logger.error("check authority issuer id failed due to transaction error. ", e); - return new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.isAuthorityIssuer(addr); } catch (Exception e) { logger.error("check authority issuer id failed.", e); - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), + e.getMessage()); + } + } + + /** + * Recognize this WeID to be an authority issuer. + * + * @param weId the WeID + * @param weIdPrivateKey the private key set + * @return true if succeeds, false otherwise + */ + @Override + public ResponseData recognizeAuthorityIssuer(String weId, + WeIdPrivateKey weIdPrivateKey) { + if (!weIdService.isWeIdExist(weId).getResult()) { + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + String addr = WeIdUtils.convertWeIdToAddress(weId); + try { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.recognizeWeId(true, addr, weIdPrivateKey.getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.recognizeWeId(true, addr, weIdPrivateKey.getPrivateKey()); + } catch (Exception e) { + logger.error("Failed to recognize authority issuer.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), + e.getMessage()); + } + } + + /** + * De-recognize this WeID to no longer be and authority issuer. + * + * @param weId the WeID + * @param weIdPrivateKey the private key set + * @return true if succeeds, false otherwise + */ + @Override + public ResponseData deRecognizeAuthorityIssuer(String weId, + WeIdPrivateKey weIdPrivateKey) { + if (!weIdService.isWeIdExist(weId).getResult()) { + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + String addr = WeIdUtils.convertWeIdToAddress(weId); + try { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.recognizeWeId(false, addr, weIdPrivateKey.getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.recognizeWeId(false, addr, weIdPrivateKey.getPrivateKey()); + } catch (Exception e) { + logger.error("Failed to recognize authority issuer.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), + e.getMessage()); } - return responseData; } /** @@ -266,186 +219,503 @@ public ResponseData isAuthorityIssuer(String weId) { */ @Override public ResponseData queryAuthorityIssuerInfo(String weId) { - ResponseData responseData = new ResponseData(); - if (!WeIdUtils.isWeIdValid(weId)) { - return new ResponseData(null, ErrorCode.WEID_INVALID); + return new ResponseData<>(null, ErrorCode.WEID_INVALID); } - Address addr = new Address(WeIdUtils.convertWeIdToAddress(weId)); try { - List rawResult = - authorityIssuerController - .getAuthorityIssuerInfoNonAccValue(addr) - .get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - if (rawResult == null) { - return new ResponseData(null, ErrorCode.AUTHORITY_ISSUER_ERROR); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.queryAuthorityIssuerInfo(weId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); } + AuthorityIssuer authorityIssuer = AuthorityIssuer.fromBlockChain(innerResp.getResult()); + return new ResponseData<>(authorityIssuer, ErrorCode.SUCCESS); + //return authEngine.getAuthorityIssuerInfoNonAccValue(weId); + } catch (Exception e) { + logger.error("query authority issuer failed.", e); + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } - DynamicArray bytes32Attributes = (DynamicArray) rawResult.get(0); - DynamicArray int256Attributes = (DynamicArray) rawResult.get(1); - - AuthorityIssuer result = new AuthorityIssuer(); - result.setWeId(weId); - String name = extractNameFromBytes32Attributes(bytes32Attributes.getValue()); - Long createDate = Long - .valueOf(int256Attributes.getValue().get(0).getValue().longValue()); - if (StringUtils.isEmpty(name) && createDate.equals(new Long(0))) { - return new ResponseData( - null, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + /** + * Get all of the authority issuer. + * + * @param index start position + * @param num number of returned authority issuer in this request + * @return Execution result + */ + @Override + public ResponseData> getAllAuthorityIssuerList(Integer index, + Integer num) { + ErrorCode errorCode = isStartEndPosValid(index, num); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + try { + com.webank.weid.blockchain.protocol.response.ResponseData> innerResp = + authorityBlockchainService.getAuthorityIssuerAddressList(index, num); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + //List addrList = authEngine.getAuthorityIssuerAddressList(index, num); + List authorityIssuerList = new ArrayList<>(); + for (String address : innerResp.getResult()) { + String weId = WeIdUtils.convertAddressToWeId(address); + ResponseData innerResponseData + = this.queryAuthorityIssuerInfo(weId); + if (innerResponseData.getResult() != null) { + authorityIssuerList.add(innerResponseData.getResult()); + } } - result.setName(name); - result.setCreated(createDate); - // Accumulator Value is unable to load due to Solidity 0.4.4 restrictions - left blank. - result.setAccValue(""); - responseData.setResult(result); - } catch (TimeoutException e) { - logger.error("query authority issuer failed due to system timeout. ", e); - return new ResponseData(null, ErrorCode.TRANSACTION_TIMEOUT); - } catch (InterruptedException | ExecutionException e) { - logger.error("query authority issuer failed due to transaction error. ", e); - return new ResponseData(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); + return new ResponseData<>(authorityIssuerList, ErrorCode.SUCCESS); } catch (Exception e) { - logger.error("query authority issuer failed.", e); - return new ResponseData(null, ErrorCode.AUTHORITY_ISSUER_ERROR); + logger.error("query authority issuer list failed.", e); + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + /** + * Register a new issuer type. + * + * @param callerAuth the caller + * @param issuerType the specified issuer type + * @return Execution result + */ + @Override + public ResponseData registerIssuerType( + WeIdAuthentication callerAuth, + String issuerType + ) { + ErrorCode innerCode = isIssuerTypeValid(issuerType); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + innerCode = isCallerAuthValid(callerAuth); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + try { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.registerIssuerType(callerAuth.getWeIdPrivateKey().getPrivateKey(), issuerType); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.registerIssuerType(issuerType, callerAuth.getWeIdPrivateKey().getPrivateKey()); + } catch (Exception e) { + logger.error("register issuer type failed.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + + /** + * Marked an issuer as the specified issuer type. + * + * @param callerAuth the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param targetIssuerWeId the weId of the issuer who will be marked as a specific issuer type + * @return Execution result + */ + @Override + public ResponseData addIssuerIntoIssuerType( + WeIdAuthentication callerAuth, + String issuerType, + String targetIssuerWeId + ) { + ErrorCode innerCode = isSpecificTypeIssuerArgsValid(callerAuth, issuerType, + targetIssuerWeId); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + try { + String issuerAddress = WeIdUtils.convertWeIdToAddress(targetIssuerWeId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.addIssuer(callerAuth.getWeIdPrivateKey().getPrivateKey(), issuerType, issuerAddress); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.addIssuer(issuerType, issuerAddress, callerAuth.getWeIdPrivateKey().getPrivateKey()); + } catch (Exception e) { + logger.error("add issuer into type failed.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + /** + * Removed an issuer from the specified issuer list. + * + * @param callerAuth the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param targetIssuerWeId the weId of the issuer to be removed from a specific issuer list + * @return Execution result + */ + @Override + public ResponseData removeIssuerFromIssuerType( + WeIdAuthentication callerAuth, + String issuerType, + String targetIssuerWeId + ) { + ErrorCode innerCode = isSpecificTypeIssuerArgsValid(callerAuth, issuerType, + targetIssuerWeId); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + try { + String issuerAddress = WeIdUtils.convertWeIdToAddress(targetIssuerWeId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.removeIssuer(callerAuth.getWeIdPrivateKey().getPrivateKey(), issuerType, issuerAddress); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + /*return authEngine.removeIssuer( + issuerType, + issuerAddress, + callerAuth.getWeIdPrivateKey().getPrivateKey());*/ + } catch (Exception e) { + logger.error("remove issuer from type failed.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + /** + * Check if the given WeId is belonging to a specific issuer type. + * + * @param issuerType the issuer type + * @param targetIssuerWeId the WeId + * @return true if yes, false otherwise + */ + @Override + public ResponseData isSpecificTypeIssuer( + String issuerType, + String targetIssuerWeId + ) { + ErrorCode errorCode = isIssuerTypeValid(issuerType); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, errorCode); + } + if (!weIdService.isWeIdExist(targetIssuerWeId).getResult()) { + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + try { + String address = WeIdUtils.convertWeIdToAddress(targetIssuerWeId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.isSpecificTypeIssuer(issuerType, address); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.isSpecificTypeIssuer(issuerType, address); + } catch (Exception e) { + logger.error("check issuer type failed.", e); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + /** + * Get all specific typed issuer in a list. + * + * @param issuerType the issuer type + * @param index the start position index + * @param num the number of issuers + * @return the list + */ + @Override + public ResponseData> getAllSpecificTypeIssuerList( + String issuerType, + Integer index, + Integer num + ) { + ErrorCode errorCode = isIssuerTypeValid(issuerType); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + errorCode = isStartEndPosValid(index, num); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + try { + com.webank.weid.blockchain.protocol.response.ResponseData> innerResp = + authorityBlockchainService.getAllSpecificTypeIssuerList(issuerType, index, num); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getSpecificTypeIssuerList(issuerType, index, num); + } catch (Exception e) { + logger.error("get all specific issuers failed.", e); + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + } + + private ErrorCode isStartEndPosValid(Integer index, Integer num) { + if (index == null || index < 0 || num == null || num <= 0 + || num > WeIdConstant.MAX_AUTHORITY_ISSUER_LIST_SIZE) { + return ErrorCode.ILLEGAL_INPUT; } - return responseData; + return ErrorCode.SUCCESS; } - private ResponseData checkRegisterAuthorityIssuerArgs( + private ErrorCode isSpecificTypeIssuerArgsValid( + WeIdAuthentication callerAuth, + String issuerType, + String targetIssuerWeId + ) { + if (!WeIdUtils.isWeIdValid(targetIssuerWeId)) { + return ErrorCode.WEID_INVALID; + } + if (!weIdService.isWeIdExist(targetIssuerWeId).getResult()) { + return ErrorCode.WEID_DOES_NOT_EXIST; + } + ErrorCode errorCode = isCallerAuthValid(callerAuth); + if (errorCode.getCode() == ErrorCode.SUCCESS.getCode()) { + return isIssuerTypeValid(issuerType); + } + return errorCode; + } + + private ErrorCode isCallerAuthValid(WeIdAuthentication callerAuth) { + if (callerAuth == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (!WeIdUtils.isWeIdValid(callerAuth.getWeId())) { + return ErrorCode.WEID_INVALID; + } + if (!weIdService.isWeIdExist(callerAuth.getWeId()).getResult()) { + return ErrorCode.WEID_DOES_NOT_EXIST; + } + if (callerAuth.getWeIdPrivateKey() == null + || StringUtils.isEmpty(callerAuth.getWeIdPrivateKey().getPrivateKey())) { + return ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL; + } + return ErrorCode.SUCCESS; + } + + private ErrorCode isIssuerTypeValid(String issuerType) { + if (StringUtils.isEmpty(issuerType)) { + return ErrorCode.ILLEGAL_INPUT; + } + if (issuerType.length() > WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH) { + return ErrorCode.SPECIFIC_ISSUER_TYPE_ILLEGAL; + } + return ErrorCode.SUCCESS; + } + + private ErrorCode checkRegisterAuthorityIssuerArgs( RegisterAuthorityIssuerArgs args) { - ResponseData responseData = new ResponseData(); + if (args == null) { - return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + return ErrorCode.ILLEGAL_INPUT; } - ResponseData checkResponse = checkAuthorityIssuerArgsValidity( + ErrorCode errorCode = checkAuthorityIssuerArgsValidity( args.getAuthorityIssuer() ); - if (!checkResponse.getResult()) { + + if (ErrorCode.SUCCESS.getCode() != errorCode.getCode()) { logger.error("register authority issuer format error!"); - return new ResponseData<>( - false, - checkResponse.getErrorCode(), - checkResponse.getErrorMessage() - ); + return errorCode; } if (args.getWeIdPrivateKey() == null || StringUtils.isEmpty(args.getWeIdPrivateKey().getPrivateKey())) { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL); + return ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL; } // Need an extra check for the existence of WeIdentity DID on chain, in Register Case. ResponseData innerResponseData = weIdService .isWeIdExist(args.getAuthorityIssuer().getWeId()); if (!innerResponseData.getResult()) { - return new ResponseData<>(false, ErrorCode.WEID_INVALID); + return ErrorCode.WEID_INVALID; } - - responseData.setResult(true); - return responseData; + return ErrorCode.SUCCESS; } - private ResponseData checkRemoveAuthorityIssuerArgs(RemoveAuthorityIssuerArgs args) { - ResponseData responseData = new ResponseData(); + private ErrorCode checkRemoveAuthorityIssuerArgs(RemoveAuthorityIssuerArgs args) { + if (args == null) { - return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + return ErrorCode.ILLEGAL_INPUT; } if (!WeIdUtils.isWeIdValid(args.getWeId())) { - return new ResponseData<>(false, ErrorCode.WEID_INVALID); + return ErrorCode.WEID_INVALID; } if (args.getWeIdPrivateKey() == null || StringUtils.isEmpty(args.getWeIdPrivateKey().getPrivateKey())) { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL); + return ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL; } - responseData.setResult(true); - return responseData; + return ErrorCode.SUCCESS; } - private ResponseData checkAuthorityIssuerArgsValidity(AuthorityIssuer args) { - ResponseData responseData = new ResponseData(); + private ErrorCode checkAuthorityIssuerArgsValidity(AuthorityIssuer args) { + if (args == null) { - return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + return ErrorCode.ILLEGAL_INPUT; } if (!WeIdUtils.isWeIdValid(args.getWeId())) { - return new ResponseData<>(false, ErrorCode.WEID_INVALID); + return ErrorCode.WEID_INVALID; } String name = args.getName(); - if (!isValidAuthorityIssuerName(name)) { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL); + if (!isValidAuthorityIssuerBytes32Param(name)) { + return ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL; } String accValue = args.getAccValue(); try { BigInteger accValueBigInteger = new BigInteger(accValue); logger.info(args.getWeId() + " accValue is: " + accValueBigInteger.longValue()); + if (accValueBigInteger.compareTo(BigInteger.ZERO) < 0) { + return ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL; + } } catch (Exception e) { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL); + logger.error("accValue is invalid.", e); + return ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL; } - responseData.setResult(true); - return responseData; - } - private ResponseData verifyAuthorityIssuerRelatedEvent( - AuthorityIssuerRetLogEventResponse event, Address addr, Integer opcode) { - ResponseData responseData = new ResponseData(); - if (event.addr.getValue().equals(addr.getValue())) { - Integer eventOpcode = event.operation.getValue().intValue(); - if (eventOpcode.equals(opcode)) { - Integer eventRetCode = event.retCode.getValue().intValue(); - if (eventRetCode.equals(ErrorCode.SUCCESS.getCode())) { - return new ResponseData<>(true, ErrorCode.SUCCESS); - } else { - responseData.setResult(false); - responseData.setErrorCode(eventRetCode); - if (eventRetCode.equals( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode())) { - responseData.setErrorMessage( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCodeDesc()); - } else if (eventRetCode.equals( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode())) { - responseData.setErrorMessage( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCodeDesc()); - } else if (eventRetCode.equals( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode())) { - responseData.setErrorMessage( - ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCodeDesc()); - } else { - responseData.setErrorCode(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode()); - responseData - .setErrorMessage(ErrorCode.AUTHORITY_ISSUER_ERROR.getCodeDesc()); - } - return responseData; + // Check additional, optional params + if (!StringUtils.isEmpty(args.getDescription()) + && !isValidAuthorityIssuerBytes32Param(args.getDescription())) { + logger.error("Authority Issuer description length illegal: ", args.getDescription()); + return ErrorCode.AUTORITY_ISSUER_DESCRIPTION_ILLEGAL; + } + List extraStr32s = args.getExtraStr32(); + List extraInts = args.getExtraInt(); + if (!CollectionUtils.isEmpty(extraStr32s)) { + if (extraStr32s.size() > WeIdConstant.AUTHORITY_ISSUER_EXTRA_PARAM_LENGTH) { + logger.error("Authority Issuer extra param size exceeds maximum."); + return ErrorCode.AUTHORITY_ISSUER_EXTRA_PARAM_ILLEGAL; + } + for (String extraStr : extraStr32s) { + if (!isValidAuthorityIssuerBytes32Param(extraStr)) { + logger.error("Authority Issuer extra String length illegal."); + return ErrorCode.AUTHORITY_ISSUER_EXTRA_PARAM_ILLEGAL; } - } else { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_OPCODE_MISMATCH); } - } else { - return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ADDRESS_MISMATCH); } + if (!CollectionUtils.isEmpty(extraInts) + && extraInts.size() > WeIdConstant.AUTHORITY_ISSUER_EXTRA_PARAM_LENGTH) { + logger.error("Authority Issuer extra param size exceeds maximum."); + return ErrorCode.AUTHORITY_ISSUER_EXTRA_PARAM_ILLEGAL; + } + return ErrorCode.SUCCESS; } - private boolean isValidAuthorityIssuerName(String name) { + private boolean isValidAuthorityIssuerBytes32Param(String name) { return !StringUtils.isEmpty(name) - && name.length() < WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH - && !StringUtils.isWhitespace(name) - && StringUtils.isAsciiPrintable(name); + && name.getBytes(StandardCharsets.UTF_8).length + < WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH + && !StringUtils.isWhitespace(name); } - private String[] loadNameToStringAttributes(String name) { - String[] nameArray = new String[16]; - // Each String item is Bytes32, so automatically compute how many indices will be used - int maxLength = WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH / 32; - int i = 0; - if (name.length() < maxLength * 32) { - maxLength = (int) Math.ceil((double) name.length() / 32.0); + @Override + public ResponseData getWeIdByOrgId(String orgId) { + if (!isValidAuthorityIssuerBytes32Param(orgId)) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL); + } + try { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.getWeIdFromOrgId(orgId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getWeIdFromOrgId(orgId); + } catch (Exception e) { + logger.error("Failed to get WeID, Error Message:{}", e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.AUTHORITY_ISSUER_ERROR); } - nameArray[i] = name.substring(i * 32, name.length()); - return nameArray; } - private String extractNameFromBytes32Attributes(List bytes32Array) { - String name = StringUtils.EMPTY; - int maxLength = WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH / 32; - for (int i = 0; i < maxLength; i++) { - name += DataTypetUtils.bytes32ToString(bytes32Array.get(i)); + @Override + public ResponseData getIssuerCount() { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.getIssuerCount(); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getIssuerCount(); + } + + @Override + public ResponseData getRecognizedIssuerCount() { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.getRecognizedIssuerCount(); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getRecognizedIssuerCount(); + } + + @Override + public ResponseData getSpecificTypeIssuerSize(String issuerType) { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.getSpecificTypeIssuerSize(issuerType); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getSpecificTypeIssuerSize(issuerType); + } + + @Override + public ResponseData getIssuerTypeCount() { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.getIssuerTypeCount(); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.getIssuerTypeCount(); + } + + @Override + public ResponseData removeIssuerType( + WeIdAuthentication callerAuth, + String issuerType + ) { + ErrorCode innerCode = isIssuerTypeValid(issuerType); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + innerCode = isCallerAuthValid(callerAuth); + if (innerCode != ErrorCode.SUCCESS) { + return new ResponseData<>(false, innerCode); + } + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + authorityBlockchainService.removeIssuerType(callerAuth.getWeIdPrivateKey().getPrivateKey(), issuerType); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + //return authEngine.removeIssuerType(issuerType, callerAuth.getWeIdPrivateKey().getPrivateKey()); + } + + @Override + public ResponseData> getIssuerTypeList(Integer index, Integer num) { + com.webank.weid.blockchain.protocol.response.ResponseData> innerResp = + authorityBlockchainService.getIssuerTypeList(index, num); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + List typeList = new ArrayList<>(); + for(com.webank.weid.blockchain.protocol.base.IssuerType type : innerResp.getResult()){ + IssuerType issuerType = IssuerType.fromBlockChain(type); + typeList.add(issuerType); } - return name; + return new ResponseData<>(typeList, ErrorCode.SUCCESS); + //return authEngine.getIssuerTypeList(index, num); } } diff --git a/src/main/java/com/webank/weid/service/impl/CptServiceImpl.java b/src/main/java/com/webank/weid/service/impl/CptServiceImpl.java index 68db8c07..9f706fe3 100644 --- a/src/main/java/com/webank/weid/service/impl/CptServiceImpl.java +++ b/src/main/java/com/webank/weid/service/impl/CptServiceImpl.java @@ -1,99 +1,180 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.service.impl; -import java.math.BigInteger; +import java.util.HashMap; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.collections4.CollectionUtils; +import java.util.Map; + +import com.webank.wedpr.selectivedisclosure.CredentialTemplateEntity; +import com.webank.wedpr.selectivedisclosure.IssuerClient; +import com.webank.wedpr.selectivedisclosure.IssuerResult; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.service.local.CptServiceLocal; +import com.webank.weid.service.local.WeIdServiceLocal; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.*; import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; -import org.bcos.web3j.crypto.Keys; -import org.bcos.web3j.crypto.Sign; -import org.bcos.web3j.crypto.Sign.SignatureData; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import com.google.common.base.Splitter; -import com.webank.weid.config.ContractConfig; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; import com.webank.weid.constant.WeIdConstant; -import com.webank.weid.contract.CptController; -import com.webank.weid.contract.CptController.RegisterCptRetLogEventResponse; -import com.webank.weid.contract.CptController.UpdateCptRetLogEventResponse; import com.webank.weid.protocol.base.Cpt; import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.WeIdAuthentication; import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.UpdateCptArgs; -import com.webank.weid.protocol.response.ResponseData; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; import com.webank.weid.protocol.response.RsvSignature; -import com.webank.weid.rpc.CptService; -import com.webank.weid.service.BaseService; -import com.webank.weid.util.DataTypetUtils; -import com.webank.weid.util.JsonSchemaValidatorUtils; -import com.webank.weid.util.SignatureUtils; -import com.webank.weid.util.WeIdUtils; +import com.webank.weid.service.rpc.CptService; +import com.webank.weid.suite.cache.CacheManager; +import com.webank.weid.suite.cache.CacheNode; /** * Service implementation for operation on CPT (Claim Protocol Type). * - * @author lingfenghe + * @author afeexian */ -@Component -public class CptServiceImpl extends BaseService implements CptService { +public class CptServiceImpl implements CptService { private static final Logger logger = LoggerFactory.getLogger(CptServiceImpl.class); + private static com.webank.weid.blockchain.rpc.CptService cptBlockchainService; - private static CptController cptController; - private static String cptControllerAddress; + private static Persistence dataDriver; + private static PersistenceType persistenceType; + //获取CPT缓存节点 + private static CacheNode> cptCahceNode = + CacheManager.registerCacheNode("SYS_CPT", 1000 * 3600 * 24L); + + public CptServiceImpl(){ + cptBlockchainService = getCptService(); + } + + private static com.webank.weid.blockchain.rpc.CptService getCptService() { + if(cptBlockchainService != null) { + return cptBlockchainService; + } else { + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("blockchain")) { + return new com.webank.weid.blockchain.service.impl.CptServiceImpl(); + } else { + // default database + return new CptServiceLocal(); + } + } + } /** - * Instantiates a new cpt service impl. + * Register a new CPT with a pre-set CPT ID, to the blockchain. + * + * @param args the args + * @param cptId the CPT ID + * @return response data */ - public CptServiceImpl() { - init(); + public ResponseData registerCpt(CptStringArgs args, Integer cptId) { + if (args == null || cptId == null || cptId <= 0) { + logger.error( + "[registerCpt1] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + try { + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(args.getWeIdAuthentication()); + Map cptJsonSchemaMap = + DataToolUtils.deserialize(args.getCptJsonSchema(), HashMap.class); + cptMapArgs.setCptJsonSchema(cptJsonSchemaMap); + return this.registerCpt(cptMapArgs, cptId); + } catch (Exception e) { + logger.error("[registerCpt1] register cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } } - private static void init() { - ContractConfig config = context.getBean(ContractConfig.class); - cptControllerAddress = config.getCptAddress(); - cptController = (CptController) getContractService(config.getCptAddress(), - CptController.class); + + /** + * This is used to register a new CPT to the blockchain. + * + * @param args the args + * @return the response data + */ + public ResponseData registerCpt(CptStringArgs args) { + + try { + if (args == null) { + logger.error( + "[registerCpt1]input CptStringArgs is null"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(args.getWeIdAuthentication()); + Map cptJsonSchemaMap = + DataToolUtils.deserialize(args.getCptJsonSchema(), HashMap.class); + cptMapArgs.setCptJsonSchema(cptJsonSchemaMap); + return this.registerCpt(cptMapArgs); + } catch (Exception e) { + logger.error("[registerCpt1] register cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } } - private static void reloadContract(String privateKey) { - cptController = - (CptController) reloadContract(cptControllerAddress, privateKey, CptController.class); + /** + * Register a new CPT with a pre-set CPT ID, to the blockchain. + * + * @param args the args + * @param cptId the CPT ID + * @return response data + */ + public ResponseData registerCpt(CptMapArgs args, Integer cptId) { + if (args == null || cptId == null || cptId <= 0) { + logger.error("[registerCpt] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + try { + ErrorCode errorCode = + this.validateCptArgs( + args.getWeIdAuthentication(), + args.getCptJsonSchema() + ); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); + } + + String weId = args.getWeIdAuthentication().getWeId(); + WeIdPrivateKey weIdPrivateKey = args.getWeIdAuthentication().getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); + RsvSignature rsvSignature = sign( + weId, + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.registerCpt(address, cptJsonSchemaNew, RsvSignature.toBlockChain(rsvSignature), + weIdPrivateKey.getPrivateKey(), cptId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); + } + ErrorCode errorCodeProcess = processTemplate(cptId, cptJsonSchemaNew); + int code = errorCodeProcess.getCode(); + if (code != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerCpt]register cpt failed, error code is {}", code); + return new ResponseData(null, ErrorCode.getTypeByErrorCode(code), innerResp.getTransactionInfo()); + } + CptBaseInfo cptBaseInfo = CptBaseInfo.fromBlockChain(innerResp.getResult()); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + /*return cptServiceEngine.registerCpt(cptId, address, cptJsonSchemaNew, rsvSignature, + weIdPrivateKey.getPrivateKey(), WeIdConstant.CPT_DATA_INDEX);*/ + + } catch (Exception e) { + logger.error("[registerCpt] register cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } } /** @@ -102,87 +183,100 @@ private static void reloadContract(String privateKey) { * @param args the args * @return the response data */ - public ResponseData registerCpt(RegisterCptArgs args) { - ResponseData responseData = new ResponseData(); + public ResponseData registerCpt(CptMapArgs args) { try { - responseData = validateRegisterCptArgs(args, responseData); - if (responseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { - return responseData; + if (args == null) { + logger.error("[registerCpt]input CptMapArgs is null"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); } + ErrorCode validateResult = + this.validateCptArgs( + args.getWeIdAuthentication(), + args.getCptJsonSchema() + ); - Address publisher = new Address(WeIdUtils.convertWeIdToAddress(args.getCptPublisher())); + if (validateResult.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, validateResult); + } - long[] longArray = new long[WeIdConstant.LONG_ARRAY_LENGTH]; - long created = System.currentTimeMillis(); - longArray[1] = created; - StaticArray intArray = DataTypetUtils.longArrayToInt256StaticArray(longArray); + String weId = args.getWeIdAuthentication().getWeId(); + WeIdPrivateKey weIdPrivateKey = args.getWeIdAuthentication().getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); + RsvSignature rsvSignature = sign( + weId, + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.registerCpt(address, cptJsonSchemaNew, RsvSignature.toBlockChain(rsvSignature), + weIdPrivateKey.getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); + } + CptBaseInfo cptBaseInfo = CptBaseInfo.fromBlockChain(innerResp.getResult()); + ErrorCode errorCodeProcess = processTemplate(cptBaseInfo.getCptId(), cptJsonSchemaNew); + int code = errorCodeProcess.getCode(); + if (code != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerCpt]register cpt failed, error code is {}", code); + return new ResponseData(null, ErrorCode.getTypeByErrorCode(code), innerResp.getTransactionInfo()); + } + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + /*return cptServiceEngine.registerCpt(address, cptJsonSchemaNew, rsvSignature, + weIdPrivateKey.getPrivateKey(), WeIdConstant.CPT_DATA_INDEX);*/ + } catch (Exception e) { + logger.error("[registerCpt] register cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } - String[] stringArray = new String[WeIdConstant.STRING_ARRAY_LENGTH]; - StaticArray bytes32Array = DataTypetUtils.stringArrayToBytes32StaticArray( - stringArray - ); + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + private ErrorCode processTemplate(Integer cptId, String cptJsonSchemaNew) { - List stringList = Splitter - .fixedLength(WeIdConstant.BYTES32_FIXED_LENGTH) - .splitToList(args.getCptJsonSchema()); - String[] jsonSchemaArray = new String[WeIdConstant.JSON_SCHEMA_ARRAY_LENGTH]; - for (int i = 0; i < stringList.size(); i++) { - jsonSchemaArray[i] = stringList.get(i); + //if the cpt is not zkp type, no need to make template. + if (!CredentialPojoUtils.isZkpCpt(cptJsonSchemaNew)) { + return ErrorCode.SUCCESS; + } + List attributeList; + try { + attributeList = JsonUtil.extractCptProperties(cptJsonSchemaNew); + IssuerResult issuerResult = IssuerClient.makeCredentialTemplate(attributeList); + CredentialTemplateEntity template = issuerResult.credentialTemplateEntity; + String templateSecretKey = issuerResult.templateSecretKey; + ResponseData resp = + getDataDriver().addOrUpdate( + DataDriverConstant.DOMAIN_ISSUER_TEMPLATE_SECRET, + String.valueOf(cptId), + templateSecretKey); + if (resp.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error("[processTemplate] save credential template to db failed."); + throw new DatabaseException("database error!"); } - StaticArray jsonSchema = - DataTypetUtils.stringArrayToBytes32StaticArray(jsonSchemaArray); - - RsvSignature rsvSignature = - sign(args.getCptPublisher(), args.getCptJsonSchema(), - args.getCptPublisherPrivateKey()); - - reloadContract(args.getCptPublisherPrivateKey().getPrivateKey()); - TransactionReceipt transactionReceipt = cptController.registerCpt( - publisher, - intArray, - bytes32Array, - jsonSchema, - rsvSignature.getV(), - rsvSignature.getR(), - rsvSignature.getS() - ).get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - - List event = CptController.getRegisterCptRetLogEvents( - transactionReceipt - ); - if (CollectionUtils.isNotEmpty(event)) { - if (DataTypetUtils.uint256ToInt(event.get(0).retCode) - == ErrorCode.CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX.getCode()) { - responseData = new ResponseData<>(null, - ErrorCode.CPT_ID_AUTHORITY_ISSUER_EXCEED_MAX); - } else if (DataTypetUtils.uint256ToInt(event.get(0).retCode) - == ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode()) { - responseData = new ResponseData<>(null, ErrorCode.CPT_PUBLISHER_NOT_EXIST); - } else { - CptBaseInfo result = new CptBaseInfo(); - result.setCptId(DataTypetUtils.uint256ToInt(event.get(0).cptId)); - result.setCptVersion(DataTypetUtils.int256ToInt(event.get(0).cptVersion)); - responseData.setResult(result); - } - } else { - responseData = new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = cptBlockchainService.putCredentialTemplate( + cptId, + template.getPublicKey().getCredentialPublicKey(), + template.getCredentialKeyCorrectnessProof()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return ErrorCode.CPT_CREDENTIAL_TEMPLATE_SAVE_ERROR; } - } catch (InterruptedException | ExecutionException e) { - responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); - logger.error( - "[CptServiceImpl] register cpt failed due to transaction execution error. ", - e - ); - } catch (TimeoutException e) { - responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_TIMEOUT); - logger.error("[CptServiceImpl] register cpt failed due to transaction timeout. ", e); + return ErrorCode.SUCCESS; } catch (Exception e) { - responseData = new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); - logger.error("[CptServiceImpl] register cpt failed due to unknown error. ", e); + logger.error("[processTemplate] process credential template failed.", e); + return ErrorCode.CPT_CREDENTIAL_TEMPLATE_SAVE_ERROR; } - - return responseData; } /** @@ -192,71 +286,33 @@ public ResponseData registerCpt(RegisterCptArgs args) { * @return the response data */ public ResponseData queryCpt(Integer cptId) { - ResponseData responseData = new ResponseData(); - List typeList; try { if (cptId == null || cptId < 0) { - responseData = new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); - return responseData; + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); } - - typeList = cptController.queryCpt(DataTypetUtils.intToUint256(cptId)).get(); - - if (typeList != null) { - if (WeIdConstant.EMPTY_ADDRESS.equals(((Address) typeList.get(0)).toString())) { - responseData = new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); - logger.error("Query cpt id : {} does not exist.", cptId); - return responseData; + String cptIdStr = String.valueOf(cptId); + ResponseData result = cptCahceNode.get(cptIdStr); + if (result == null) { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.queryCpt(cptId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); } - Cpt cpt = new Cpt(); - cpt.setCptId(cptId); - - cpt.setCptPublisher( - WeIdUtils.convertAddressToWeId(((Address) typeList.get(0)).toString())); - - long[] longArray = DataTypetUtils.int256DynamicArrayToLongArray( - (DynamicArray) typeList.get(1) - ); - cpt.setCptVersion((int) longArray[0]); - cpt.setCreated(longArray[1]); - cpt.setUpdated(longArray[2]); - - String[] jsonSchemaArray = - DataTypetUtils.bytes32DynamicArrayToStringArrayWithoutTrim( - (DynamicArray) typeList.get(3) - ); - String jsonSchema = StringUtils.EMPTY; - for (int i = 0; i < jsonSchemaArray.length; i++) { - jsonSchema = jsonSchema + jsonSchemaArray[i]; - } - cpt.setCptJsonSchema(jsonSchema.trim()); - - int v = DataTypetUtils.uint8ToInt((Uint8) typeList.get(4)); - byte[] r = DataTypetUtils.bytes32ToBytesArray((Bytes32) typeList.get(5)); - byte[] s = DataTypetUtils.bytes32ToBytesArray((Bytes32) typeList.get(6)); - Sign.SignatureData signatureData = SignatureUtils - .rawSignatureDeserialization(v, r, s); - String cptSignature = - new String( - SignatureUtils.base64Encode( - SignatureUtils.simpleSignatureSerialization(signatureData))); - cpt.setCptSignature(cptSignature); - - responseData.setResult(cpt); + Cpt cpt = Cpt.fromBlockChain(innerResp.getResult()); + cptCahceNode.put(cptIdStr, new ResponseData<>(cpt, ErrorCode.SUCCESS)); + return new ResponseData<>(cpt, ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + /*result = cptServiceEngine.queryCpt(cptId, WeIdConstant.CPT_DATA_INDEX); + if (result.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) { + cptCahceNode.put(cptIdStr, result); + }*/ } - } catch (InterruptedException | ExecutionException e) { - responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); - logger.error( - "[CptServiceImpl] query cpt failed due to transaction execution error. ", - e - ); + return result; } catch (Exception e) { - responseData = new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); - logger.error("[CptServiceImpl] query cpt failed due to unknown error. ", e); + logger.error("[updateCpt] query cpt failed due to unknown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); } - - return responseData; } /** @@ -265,210 +321,207 @@ public ResponseData queryCpt(Integer cptId) { * @param args the args * @return the response data */ - public ResponseData updateCpt(UpdateCptArgs args) { - ResponseData responseData = new ResponseData<>(); + public ResponseData updateCpt(CptStringArgs args, Integer cptId) { try { - responseData = validateUpdateCptArgs(args, responseData); - if (responseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { - return responseData; + if (args == null) { + logger.error("[updateCpt1]input UpdateCptArgs is null"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); } - Uint256 cptId = DataTypetUtils.intToUint256(args.getCptId()); - - Address publisher = new Address(WeIdUtils.convertWeIdToAddress(args.getCptPublisher())); + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(args.getWeIdAuthentication()); + cptMapArgs.setCptJsonSchema( + DataToolUtils.deserialize(args.getCptJsonSchema(), HashMap.class)); + return this.updateCpt(cptMapArgs, cptId); + } catch (Exception e) { + logger.error("[updateCpt1] update cpt failed due to unkown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } - long[] longArray = new long[WeIdConstant.LONG_ARRAY_LENGTH]; - long updated = System.currentTimeMillis(); - longArray[2] = updated; - StaticArray intArray = DataTypetUtils.longArrayToInt256StaticArray(longArray); + /** + * This is used to update a CPT data which has been register. + * + * @param args the args + * @return the response data + */ + public ResponseData updateCpt(CptMapArgs args, Integer cptId) { - String[] stringArray = new String[WeIdConstant.STRING_ARRAY_LENGTH]; - StaticArray bytes32Array = - DataTypetUtils.stringArrayToBytes32StaticArray(stringArray); + try { + if (args == null) { + logger.error("[updateCpt]input UpdateCptArgs is null"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + if (cptId == null || cptId.intValue() < 0) { + logger.error("[updateCpt]input cptId illegal"); + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + ErrorCode errorCode = + this.validateCptArgs( + args.getWeIdAuthentication(), + args.getCptJsonSchema() + ); - List stringList = Splitter - .fixedLength(WeIdConstant.BYTES32_FIXED_LENGTH) - .splitToList(args.getCptJsonSchema()); - String[] jsonSchemaArray = new String[WeIdConstant.JSON_SCHEMA_ARRAY_LENGTH]; - for (int i = 0; i < stringList.size(); i++) { - jsonSchemaArray[i] = stringList.get(i); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, errorCode); } - StaticArray jsonSchema = DataTypetUtils.stringArrayToBytes32StaticArray( - jsonSchemaArray - ); + String weId = args.getWeIdAuthentication().getWeId(); + WeIdPrivateKey weIdPrivateKey = args.getWeIdAuthentication().getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.cptSchemaToString(args); RsvSignature rsvSignature = sign( - args.getCptPublisher(), - args.getCptJsonSchema(), - args.getCptPublisherPrivateKey() - ); - - reloadContract(args.getCptPublisherPrivateKey().getPrivateKey()); - TransactionReceipt transactionReceipt = cptController.updateCpt( - cptId, - publisher, - intArray, - bytes32Array, - jsonSchema, - rsvSignature.getV(), - rsvSignature.getR(), - rsvSignature.getS() - ).get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - - List event = CptController.getUpdateCptRetLogEvents( - transactionReceipt - ); - if (CollectionUtils.isNotEmpty(event)) { - if (DataTypetUtils.uint256ToInt(event.get(0).retCode) - == ErrorCode.CPT_NOT_EXISTS.getCode()) { - responseData = new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); - logger.error("Update cpt id : {} does not exist.", args.getCptId()); - } else if (DataTypetUtils.uint256ToInt(event.get(0).retCode) - == ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode()) { - responseData = new ResponseData<>(null, ErrorCode.CPT_PUBLISHER_NOT_EXIST); - } else { - CptBaseInfo result = new CptBaseInfo(); - result.setCptId(DataTypetUtils.uint256ToInt(event.get(0).cptId)); - result.setCptVersion(DataTypetUtils.int256ToInt(event.get(0).cptVersion)); - responseData.setResult(result); - } + weId, + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.updateCpt( + address, + cptJsonSchemaNew, + RsvSignature.toBlockChain(rsvSignature), + weIdPrivateKey.getPrivateKey(), + cptId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); } - } catch (InterruptedException | ExecutionException e) { - responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); - logger.error( - "[CptServiceImpl] update cpt failed due to transaction execution error. ", - e - ); - } catch (TimeoutException e) { - responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_TIMEOUT); - logger.error("[CptServiceImpl] update cpt failed due to transaction timeout. ", e); + cptCahceNode.remove(String.valueOf(cptId)); + ErrorCode errorCodeProcess = processTemplate(cptId, cptJsonSchemaNew); + int code = errorCodeProcess.getCode(); + if (code != ErrorCode.SUCCESS.getCode()) { + logger.error("[updateCpt]update cpt failed, error code is {}", code); + return new ResponseData(null, ErrorCode.getTypeByErrorCode(code), innerResp.getTransactionInfo()); + } + CptBaseInfo cptBaseInfo = CptBaseInfo.fromBlockChain(innerResp.getResult()); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + /* ResponseData result = cptServiceEngine.updateCpt( + cptId, + address, + cptJsonSchemaNew, + rsvSignature, + weIdPrivateKey.getPrivateKey(), + WeIdConstant.CPT_DATA_INDEX); + if (result.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) { + cptCahceNode.remove(String.valueOf(cptId)); + } + return result;*/ } catch (Exception e) { - responseData = new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); - logger.error("[CptServiceImpl] update cpt failed due to unkown error. ", e); + logger.error("[updateCpt] update cpt failed due to unkown error. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); } - - return responseData; } private RsvSignature sign( - String cptPublisher, String jsonSchema, WeIdPrivateKey cptPublisherPrivateKey) - throws Exception { + String cptPublisher, + String jsonSchema, + WeIdPrivateKey cptPublisherPrivateKey) { + StringBuilder sb = new StringBuilder(); sb.append(cptPublisher); sb.append(WeIdConstant.PIPELINE); sb.append(jsonSchema); - SignatureData signatureData = - SignatureUtils.signMessage(sb.toString(), cptPublisherPrivateKey.getPrivateKey()); - Uint8 v = DataTypetUtils.intToUnt8(Integer.valueOf(signatureData.getV())); - Bytes32 r = DataTypetUtils.bytesArrayToBytes32(signatureData.getR()); - Bytes32 s = DataTypetUtils.bytesArrayToBytes32(signatureData.getS()); - - RsvSignature rsvSignature = new RsvSignature(); - rsvSignature.setV(v); - rsvSignature.setR(r); - rsvSignature.setS(s); - return rsvSignature; + return DataToolUtils.signToRsvSignature( + sb.toString(), cptPublisherPrivateKey.getPrivateKey()); } - private ResponseData validateRegisterCptArgs( - RegisterCptArgs args, - ResponseData responseData) throws Exception { + private ErrorCode validateCptArgs( + WeIdAuthentication weIdAuthentication, + Map cptJsonSchemaMap) throws Exception { - ResponseData responseDataReq = responseData; - if (args == null) { - logger.error("input RegisterCptArgs is null"); - responseDataReq = new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); - return responseDataReq; + if (weIdAuthentication == null) { + logger.error("Input cpt weIdAuthentication is invalid."); + return ErrorCode.WEID_AUTHORITY_INVALID; } - if (!WeIdUtils.isWeIdValid(args.getCptPublisher())) { - logger.error("Input cpt publisher : {} is invalid.", args.getCptPublisher()); - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_INVALID); - return responseDataReq; + String weId = weIdAuthentication.getWeId(); + if (!WeIdUtils.isWeIdValid(weId)) { + logger.error("Input cpt publisher : {} is invalid.", weId); + return ErrorCode.WEID_INVALID; } - if (!JsonSchemaValidatorUtils.isCptJsonSchemaValid(args.getCptJsonSchema())) { - logger.error("Input cpt json schema : {} is invalid.", args.getCptJsonSchema()); - responseDataReq = new ResponseData<>(null, ErrorCode.CPT_JSON_SCHEMA_INVALID); - return responseDataReq; + ErrorCode errorCode = validateCptJsonSchemaMap(cptJsonSchemaMap); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return errorCode; } - - if (null == args.getCptPublisherPrivateKey() - || StringUtils.isEmpty(args.getCptPublisherPrivateKey().getPrivateKey())) { + String cptJsonSchema = DataToolUtils.serialize(cptJsonSchemaMap); + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("Input cpt json schema : {} is invalid.", cptJsonSchemaMap); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + WeIdPrivateKey weIdPrivateKey = weIdAuthentication.getWeIdPrivateKey(); + if (weIdPrivateKey == null + || StringUtils.isEmpty(weIdPrivateKey.getPrivateKey())) { logger.error( - "Input cpt publisher private key : {} is in valid.", - args.getCptPublisherPrivateKey() + "Input cpt publisher private key : {} is in valid.", + weIdPrivateKey ); - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_INVALID); - return responseDataReq; + return ErrorCode.WEID_PRIVATEKEY_INVALID; } - if (!validatePrivateKeyWeIdMatches(args.getCptPublisherPrivateKey(), - args.getCptPublisher())) { - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + if (!WeIdUtils.validatePrivateKeyWeIdMatches(weIdPrivateKey, weId)) { + return ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH; } - - return responseDataReq; + return ErrorCode.SUCCESS; } - private boolean validatePrivateKeyWeIdMatches(WeIdPrivateKey cptPublisherPrivateKey, - String cptPublisher) { - boolean isMatch = false; - - try { - BigInteger publicKey = SignatureUtils - .publicKeyFromPrivate(new BigInteger(cptPublisherPrivateKey.getPrivateKey())); - String address1 = "0x" + Keys.getAddress(publicKey); - String address2 = WeIdUtils.convertWeIdToAddress(cptPublisher); - if (address1.equals(address2)) { - isMatch = true; - } - } catch (Exception e) { - logger.error("Validate private key We Id matches failed. Error message :{}", e); - return isMatch; + private ErrorCode validateCptJsonSchemaMap( + Map cptJsonSchemaMap) throws Exception { + if (cptJsonSchemaMap == null || cptJsonSchemaMap.isEmpty()) { + logger.error("Input cpt json schema is invalid."); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; } - - return isMatch; + //String cptJsonSchema = JsonUtil.objToJsonStr(cptJsonSchemaMap); + String cptJsonSchema = DataToolUtils.serialize(cptJsonSchemaMap); + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("Input cpt json schema : {} is invalid.", cptJsonSchemaMap); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + return ErrorCode.SUCCESS; } - private ResponseData validateUpdateCptArgs( - UpdateCptArgs args, ResponseData responseData) throws Exception { - ResponseData responseDataReq = responseData; - if (args == null) { - logger.error("input UpdateCptArgs is null"); - responseDataReq = new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); - return responseDataReq; - } - if (!WeIdUtils.isWeIdValid(args.getCptPublisher())) { - logger.error("Input cpt publisher : {} is invalid.", args.getCptPublisher()); - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_INVALID); - return responseDataReq; + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CptService#queryCredentialTemplate(java.lang.Integer) + */ + @Override + public ResponseData queryCredentialTemplate(Integer cptId) { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.queryCredentialTemplate(cptId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + //return cptServiceEngine.queryCredentialTemplate(cptId); + } - if (!JsonSchemaValidatorUtils.isCptJsonSchemaValid(args.getCptJsonSchema())) { - logger.error("Input cpt json schema : {} is in valid.", args.getCptJsonSchema()); - responseDataReq = new ResponseData<>(null, ErrorCode.CPT_JSON_SCHEMA_INVALID); - return responseDataReq; - } - if (null == args.getCptPublisherPrivateKey() - || StringUtils.isEmpty(args.getCptPublisherPrivateKey().getPrivateKey())) { - logger.error( - "Input cpt publisher private key : {} is in valid.", - args.getCptPublisherPrivateKey() - ); - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_INVALID); - return responseDataReq; + @Override + public ResponseData> getCptIdList(Integer startPos, Integer num) { + if (startPos < 0 || num < 1) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); } - - if (!validatePrivateKeyWeIdMatches(args.getCptPublisherPrivateKey(), - args.getCptPublisher())) { - responseDataReq = new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + com.webank.weid.blockchain.protocol.response.ResponseData> innerResp = + cptBlockchainService.getCptIdList(startPos, num); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + //return cptServiceEngine.getCptIdList(startPos, num, WeIdConstant.CPT_DATA_INDEX); + } - return responseDataReq; + @Override + public ResponseData getCptCount() { + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + cptBlockchainService.getCptCount(); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), innerResp.getTransactionInfo()); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS, innerResp.getTransactionInfo()); + //return cptServiceEngine.getCptCount(WeIdConstant.CPT_DATA_INDEX); } } diff --git a/src/main/java/com/webank/weid/service/impl/CredentialPojoServiceImpl.java b/src/main/java/com/webank/weid/service/impl/CredentialPojoServiceImpl.java new file mode 100644 index 00000000..91ea93ac --- /dev/null +++ b/src/main/java/com/webank/weid/service/impl/CredentialPojoServiceImpl.java @@ -0,0 +1,2356 @@ + +package com.webank.weid.service.impl; + +import com.networknt.schema.ValidationMessage; +import com.webank.wedpr.common.Utils; +import com.webank.wedpr.selectivedisclosure.*; +import com.webank.wedpr.selectivedisclosure.proto.Predicate; +import com.webank.wedpr.selectivedisclosure.proto.VerificationRule; +import com.webank.weid.constant.*; +import com.webank.weid.constant.CredentialConstant.CredentialProofType; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.cpt.Cpt101; +import com.webank.weid.protocol.cpt.Cpt111; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.rpc.CptService; +import com.webank.weid.service.rpc.CredentialPojoService; +import com.webank.weid.service.rpc.WeIdService; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.*; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.*; +import java.util.stream.Collectors; + + +/** + * Service implementations for operations on CredentialPojo. + * + * @author tonychen 2019年4月17日 + */ +public class CredentialPojoServiceImpl implements CredentialPojoService { + + private static final Logger logger = LoggerFactory.getLogger(CredentialPojoServiceImpl.class); + private static final String NOT_DISCLOSED = + CredentialFieldDisclosureValue.NOT_DISCLOSED.getStatus().toString(); + private static final String DISCLOSED = + CredentialFieldDisclosureValue.DISCLOSED.getStatus().toString(); + private static final String EXISTED = + CredentialFieldDisclosureValue.EXISTED.getStatus().toString(); + private static WeIdService weIdService; + private static CptService cptService; + private static Persistence dataDriver; + private static PersistenceType persistenceType; + //private static PdfTransportation pdfTransportation; + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + private static WeIdService getWeIdService() { + if (weIdService == null) { + weIdService = new WeIdServiceImpl(); + } + return weIdService; + } + + private static CptService getCptService() { + if (cptService == null) { + cptService = new CptServiceImpl(); + } + return cptService; + } + + /*private static PdfTransportation getPdfTransportation() { + if (pdfTransportation == null) { + pdfTransportation = new PdfTransportationImpl(); + } + return pdfTransportation; + }*/ + + /** + * Salt generator. Automatically fillin the map structure in a recursive manner. + * + * @param map the passed map (claim, salt or alike) + * @param fixed fixed value if required to use + */ + public static void generateSalt(Map map, Object fixed) { + for (Map.Entry entry : map.entrySet()) { + Object value = entry.getValue(); + if (value instanceof Map) { + generateSalt((HashMap) value, fixed); + } else if (value instanceof List) { + boolean isMapOrList = generateSaltFromList((ArrayList) value, fixed); + if (!isMapOrList) { + if (fixed == null) { + addSalt(entry); + } else { + entry.setValue(fixed); + } + } + } else { + if (fixed == null) { + addSalt(entry); + } else { + entry.setValue(fixed); + } + } + } + } + + private static void addSalt(Map.Entry entry) { + String salt = DataToolUtils.getRandomSalt(); + entry.setValue(salt); + } + + private static boolean generateSaltFromList(List objList, Object fixed) { + List list = (List) objList; + for (Object obj : list) { + if (obj instanceof Map) { + generateSalt((HashMap) obj, fixed); + } else if (obj instanceof List) { + boolean result = generateSaltFromList((ArrayList) obj, fixed); + if (!result) { + return result; + } + } else { + return false; + } + } + return true; + } + + /** + * 校验claim、salt和disclosureMap的格式是否一致. + */ + private static boolean validCredentialMapArgs(Map claim, + Map salt, Map disclosureMap) { + + //检查是否为空 + if (claim == null || salt == null || disclosureMap == null) { + return false; + } + + //检查每个map里的key个数是否相同 + if (!claim.keySet().equals(salt.keySet())) { + return false; + } + + //检查key值是否一致 + for (Map.Entry entry : disclosureMap.entrySet()) { + String k = entry.getKey(); + Object v = entry.getValue(); + //如果disclosureMap中的key在claim中没有则返回false + if (!claim.containsKey(k)) { + return false; + } + Object saltV = salt.get(k); + Object claimV = claim.get(k); + if (v instanceof Map) { + //递归检查 + if (!validCredentialMapArgs((HashMap) claimV, (HashMap) saltV, (HashMap) v)) { + return false; + } + } else if (v instanceof List) { + if (!validCredentialListArgs( + (ArrayList) claimV, + (ArrayList) saltV, + (ArrayList) v + )) { + return false; + } + } + } + return true; + } + + private static boolean validCredentialListArgs( + List claimList, + List saltList, + List disclosureList) { + //检查是否为空 + if (claimList == null || saltList == null || disclosureList == null) { + return false; + } + if (claimList.size() != saltList.size()) { + return false; + } + for (int i = 0; i < disclosureList.size(); i++) { + Object disclosureObj = disclosureList.get(i); + Object claimObj = claimList.get(i); + Object saltObj = saltList.get(i); + if (disclosureObj instanceof Map) { + boolean result = + validCredentialListArgs( + claimList, + saltList, + (HashMap) disclosureObj + ); + if (!result) { + return result; + } + } else if (disclosureObj instanceof List) { + boolean result = + validCredentialListArgs( + (ArrayList) claimObj, + (ArrayList) saltObj, + (ArrayList) disclosureObj + ); + if (!result) { + return result; + } + } + } + return true; + } + + private static boolean validCredentialListArgs( + List claimList, + List saltList, + Map disclosure + ) { + + if (claimList == null || saltList == null || saltList.size() != claimList.size()) { + return false; + } + + for (int i = 0; i < claimList.size(); i++) { + Object claim = claimList.get(i); + Object salt = saltList.get(i); + boolean result = validCredentialMapArgs((HashMap) claim, (HashMap) salt, disclosure); + if (!result) { + return result; + } + } + return true; + } + + //向policy中补充缺失的key + private static void addKeyToPolicy( + Map disclosureMap, + Map claimMap + ) { + for (Map.Entry entry : claimMap.entrySet()) { + String claimK = entry.getKey(); + Object claimV = entry.getValue(); + if (claimV instanceof Map) { + HashMap claimHashMap = (HashMap) claimV; + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, new HashMap()); + } + HashMap disclosureHashMap = (HashMap) disclosureMap.get(claimK); + addKeyToPolicy(disclosureHashMap, claimHashMap); + } else if (claimV instanceof List) { + ArrayList claimList = (ArrayList) claimV; + //判断claimList中是否包含Map结构,还是单一结构 + boolean isSampleList = isSampleListForClaim(claimList); + if (isSampleList) { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, Integer.parseInt(NOT_DISCLOSED)); + } + } else { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, new ArrayList()); + } + ArrayList disclosureList = (ArrayList) disclosureMap.get(claimK); + addKeyToPolicyList(disclosureList, claimList); + } + } else { + if (!disclosureMap.containsKey(claimK)) { + disclosureMap.put(claimK, Integer.parseInt(NOT_DISCLOSED)); + } + } + } + } + + private static void addKeyToPolicyList( + ArrayList disclosureList, + ArrayList claimList + ) { + for (int i = 0; i < claimList.size(); i++) { + Object claimObj = claimList.get(i); + if (claimObj instanceof Map) { + Object disclosureObj = disclosureList.size() == 0 ? null : disclosureList.get(0); + if (disclosureObj == null) { + disclosureList.add(new HashMap()); + } + HashMap disclosureHashMap = (HashMap) disclosureList.get(0); + addKeyToPolicy(disclosureHashMap, (HashMap) claimObj); + break; + } else if (claimObj instanceof List) { + Object disclosureObj = disclosureList.get(i); + if (disclosureObj == null) { + disclosureList.add(new ArrayList()); + } + ArrayList disclosureArrayList = (ArrayList) disclosureList.get(i); + addKeyToPolicyList(disclosureArrayList, (ArrayList) claimObj); + } + } + } + + private static boolean isSampleListForClaim(ArrayList claimList) { + if (CollectionUtils.isEmpty(claimList)) { + return true; + } + Object claimObj = claimList.get(0); + if (claimObj instanceof Map) { + return false; + } + if (claimObj instanceof List) { + return isSampleListForClaim((ArrayList) claimObj); + } + return true; + } + + private static void addSelectSalt( + Map disclosureMap, + Map saltMap, + Map claim, + boolean isZkp + ) { + for (Map.Entry entry : disclosureMap.entrySet()) { + String disclosureKey = entry.getKey(); + Object value = entry.getValue(); + Object saltV = saltMap.get(disclosureKey); + Object claimV = claim.get(disclosureKey); + if (value == null) { + throw new WeIdBaseException(ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL); + } else if ((value instanceof Map) && (claimV instanceof Map)) { + addSelectSalt((HashMap) value, (HashMap) saltV, (HashMap) claimV, isZkp); + } else if (value instanceof List) { + addSaltForList( + (ArrayList) value, + (ArrayList) saltV, + (ArrayList) claimV, + isZkp + ); + } else { + addHashToClaim(saltMap, claim, disclosureKey, value, saltV, claimV, isZkp); + } + } + } + + private static void addHashToClaim( + Map saltMap, + Map claim, + String disclosureKey, + Object value, + Object saltV, + Object claimV, + boolean isZkp + ) { + + if (isZkp) { + if ((value instanceof Map) || !(((Integer) value).equals(Integer.parseInt(DISCLOSED)) + && claim.containsKey(disclosureKey))) { + String hash = + CredentialPojoUtils.getFieldSaltHash( + String.valueOf(claimV), + String.valueOf(saltV) + ); + claim.put(disclosureKey, hash); + } + } else { + + if (((Integer) value).equals(Integer.parseInt(NOT_DISCLOSED)) + && claim.containsKey(disclosureKey)) { + saltMap.put(disclosureKey, NOT_DISCLOSED); + String hash = + CredentialPojoUtils.getFieldSaltHash( + String.valueOf(claimV), + String.valueOf(saltV) + ); + claim.put(disclosureKey, hash); + } + } + } + + private static void addSaltForList( + List disclosures, + List salt, + List claim, + boolean isZkp) { + for (int i = 0; claim != null && i < disclosures.size(); i++) { + Object disclosureObj = disclosures.get(i); + Object claimObj = claim.get(i); + Object saltObj = salt.get(i); + if (disclosureObj instanceof Map) { + addSaltForList((HashMap) disclosureObj, salt, claim, isZkp); + } else if (disclosureObj instanceof List) { + addSaltForList( + (ArrayList) disclosureObj, + (ArrayList) saltObj, + (ArrayList) claimObj, + isZkp + ); + } + } + } + + private static void addSaltForList( + Map disclosures, + List salt, + List claim, + boolean isZkp + ) { + for (int i = 0; claim != null && i < claim.size(); i++) { + Object claimObj = claim.get(i); + Object saltObj = salt.get(i); + addSelectSalt(disclosures, (HashMap) saltObj, (HashMap) claimObj, isZkp); + } + } + + private static ErrorCode verifyContent( + CredentialPojo credential, + String publicKey, + boolean offLine, + String methodId + ) { + ErrorCode errorCode; + try { + errorCode = verifyContentInner(credential, publicKey, offLine, methodId); + } catch (WeIdBaseException ex) { + logger.error("[verifyContent] verify credential has exception.", ex); + return ex.getErrorCode(); + } + // System CPT business related check + if (errorCode == ErrorCode.SUCCESS + && CredentialPojoUtils.isSystemCptId(credential.getCptId())) { + errorCode = verifySystemCptClaimInner(credential); + } + return errorCode; + } + + private static ErrorCode verifySystemCptClaimInner(CredentialPojo credential) { + if (credential.getCptId().intValue() == CredentialConstant.EMBEDDED_TIMESTAMP_CPT) { + return verifyTimestampClaim(credential); + } + if (credential.getCptId().intValue() == CredentialConstant.AUTHORIZATION_CPT) { + return verifyAuthClaim(credential); + } + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyAuthClaim(CredentialPojo credential) { + Cpt101 authInfo; + try { + authInfo = DataToolUtils.mapToObj(credential.getClaim(), Cpt101.class); + } catch (Exception e) { + logger.error("Failed to deserialize authorization information."); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + ErrorCode errorCode = verifyAuthInfo(authInfo); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + // Extra check 1: cannot authorize other WeID's resources + String issuerWeId = credential.getIssuer(); + if (!issuerWeId.equalsIgnoreCase(authInfo.getFromWeId())) { + return ErrorCode.AUTHORIZATION_CANNOT_AUTHORIZE_OTHER_WEID_RESOURCE; + } + // TODO Extra check 2: check service url endpoint exposed or not? + // Need getWeIdDocument() check + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyTimestampClaim(CredentialPojo credential) { + Map claim = credential.getClaim(); + if (((String) claim.get("timestampAuthority")) + .contains(TimestampUtils.WESIGN_AUTHORITY_NAME)) { + String hashValue = (String) claim.get("claimHash"); + String authoritySignature = (String) claim.get("authoritySignature"); + Long timestamp = (long) claim.get("timestamp"); + ResponseData resp = + TimestampUtils.verifyWeSignTimestamp(hashValue, authoritySignature, timestamp); + if (!resp.getResult()) { + return ErrorCode.getTypeByErrorCode(resp.getErrorCode()); + } + } + return ErrorCode.SUCCESS; + } + + private static ErrorCode verifyContentInner( + CredentialPojo credential, + String publicKey, + boolean offline, + String methodId + ) { + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credential); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return checkResp; + } + if (credential.getCptId() == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + .intValue()) { + logger.error("Embedded Credential is obsoleted. Please use embedded Credential Pojo."); + return ErrorCode.CPT_ID_ILLEGAL; + } + if (credential.getCptId() == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT + .intValue() || credential.getCptId() == CredentialConstant.EMBEDDED_TIMESTAMP_CPT + .intValue()) { + // This is a multi-signed Credential. We firstly verify itself (i.e. external check) + ErrorCode errorCode = verifySingleSignedCredential( + credential, publicKey, offline, methodId); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + // Then, we verify its list members one-by-one + List innerCredentialList; + try { + if (credential.getClaim().get("credentialList") instanceof String) { + // For selectively-disclosed credential, stop here. External check is enough. + return ErrorCode.SUCCESS; + } else { + innerCredentialList = (ArrayList) credential.getClaim().get("credentialList"); + } + } catch (Exception e) { + logger.error("the credential claim data illegal.", e); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + for (Object innerCredentialObject : innerCredentialList) { + // PublicKey can only be used in the passed-external check, so pass-in null key + try { + CredentialPojo innerCredential; + if (!(innerCredentialObject instanceof CredentialPojo)) { + Map map = (Map) innerCredentialObject; + innerCredential = DataToolUtils + .mapToObj(map, CredentialPojo.class); + } else { + innerCredential = (CredentialPojo) innerCredentialObject; + } + errorCode = verifyContentInner( + innerCredential, null, offline, methodId); + if (errorCode != ErrorCode.SUCCESS) { + return errorCode; + } + } catch (Exception e) { + logger.error("Failed to convert credentialPojo to object.", e); + return ErrorCode.ILLEGAL_INPUT; + } + } + return ErrorCode.SUCCESS; + } + return verifySingleSignedCredential(credential, publicKey, offline, methodId); + } + + private static ErrorCode verifySingleSignedCredential( + CredentialPojo credential, + String publicKey, + boolean offline, + String methodId + ) { + ErrorCode errorCode = verifyCptFormat( + credential.getCptId(), + credential.getClaim(), + CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt()), + offline + ); + if (ErrorCode.SUCCESS.getCode() != errorCode.getCode()) { + return errorCode; + } + Map salt = credential.getSalt(); + String rawData; + if (CredentialPojoUtils.isEmbeddedCredential(credential)) { + List objList = (ArrayList) credential.getClaim().get("credentialList"); + List credentialList = new ArrayList<>(); + try { + for (Object obj : objList) { + if (obj instanceof CredentialPojo) { + credentialList.add((CredentialPojo) obj); + } else { + credentialList.add(DataToolUtils + .mapToObj((HashMap) obj, CredentialPojo.class)); + } + } + } catch (Exception e) { + logger.error("Failed to convert credentialPojo: " + e.getMessage(), e); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + rawData = CredentialPojoUtils.getEmbeddedCredentialThumbprintWithoutSig(credentialList); + } else { + rawData = CredentialPojoUtils + .getCredentialThumbprintWithoutSig(credential, salt, null); + } + String issuerWeid = credential.getIssuer(); + if (StringUtils.isEmpty(publicKey)) { + // Fetch public key from chain + ResponseData innerResponseData = + getWeIdService().getWeIdDocument(issuerWeid); + if (innerResponseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "Error occurred when fetching WeIdentity DID document for: {}, msg: {}", + issuerWeid, innerResponseData.getErrorMessage()); + return ErrorCode.getTypeByErrorCode(innerResponseData.getErrorCode()); + } else { + WeIdDocument weIdDocument = innerResponseData.getResult(); + errorCode = DataToolUtils.verifySignatureFromWeId( + rawData, credential.getSignature(), weIdDocument, methodId); + return errorCode; + } + } else { + boolean result; + try { + result = DataToolUtils.verifySignature(rawData, + credential.getSignature(), new BigInteger(publicKey)); + + } catch (Exception e) { + logger.error("[verifyContent] verify signature fail.", e); + return ErrorCode.CREDENTIAL_SIGNATURE_BROKEN; + } + if (!result) { + return ErrorCode.CREDENTIAL_VERIFY_FAIL; + } + return ErrorCode.SUCCESS; + } + } + + + private static ErrorCode verifyCptFormat( + Integer cptId, Map claim, + boolean isSelectivelyDisclosed, + boolean offline + ) { + if (cptId == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT.intValue()) { + if (!claim.containsKey("credentialList")) { + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } else { + return ErrorCode.SUCCESS; + } + } + if (cptId == CredentialConstant.EMBEDDED_TIMESTAMP_CPT.intValue()) { + if (claim.containsKey("credentialList") && claim.containsKey("claimHash") + && claim.containsKey("timestampAuthority") && claim.containsKey("timestamp") + && claim.containsKey("authoritySignature")) { + return ErrorCode.SUCCESS; + } else { + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + } + try { + if (offline) { + return ErrorCode.SUCCESS; + } + String claimStr = DataToolUtils.serialize(claim); + Cpt cpt = getCptService().queryCpt(cptId).getResult(); + if (cpt == null) { + logger.error(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCodeDesc()); + return ErrorCode.CREDENTIAL_CPT_NOT_EXISTS; + } + //String cptJsonSchema = JsonUtil.objToJsonStr(cpt.getCptJsonSchema()); + String cptJsonSchema = DataToolUtils.serialize(cpt.getCptJsonSchema()); + + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCodeDesc()); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; + } + if (!isSelectivelyDisclosed) { + Set checkRes = DataToolUtils.checkJsonVersusSchema( + claimStr, cptJsonSchema); + if (checkRes.size() != 0) { + logger.error(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCodeDesc()); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } + } + return ErrorCode.SUCCESS; + } catch (Exception e) { + logger.error( + "Generic error occurred during verify cpt format when verifyCredential: ", e); + return ErrorCode.CREDENTIAL_ERROR; + } + } + + private static ResponseData verifyZkpCredential(CredentialPojo credential) { + + Map proof = credential.getProof(); + String encodedVerificationRule = (String) proof + .get(ParamKeyConstant.PROOF_ENCODEDVERIFICATIONRULE); + String verificationRequest = (String) proof.get(ParamKeyConstant.PROOF_VERIFICATIONREQUEST); + VerifierResult verifierResult = + VerifierClient.verifyProof(encodedVerificationRule, verificationRequest); + if (verifierResult.wedprErrorMessage == null) { + return new ResponseData(true, ErrorCode.SUCCESS); + } + + return new ResponseData(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); + } + + private static Boolean isZkpCredential(CredentialPojo credential) { + + List types = credential.getType(); + for (String type : types) { + if (StringUtils.equals(type, CredentialType.ZKP.getName())) { + return true; + } + } + return false; + } + + /** + * user build credential Info map and makeCredential. + */ + private static UserResult makeCredential( + CredentialPojo preCredential, + String claimJson, + Integer cptId, + WeIdAuthentication weIdAuthentication) { + + Map credentialInfoMap = buildCredentialInfo(preCredential, claimJson); + + ResponseData res = getCptService().queryCredentialTemplate(cptId); + CredentialTemplateEntity credentialTemplate = res.getResult(); + + UserResult userResult = UserClient.makeCredential(credentialInfoMap, credentialTemplate); + + // masterSecret is saved by User + String masterSecret = userResult.masterSecret; + String credentialSecretsBlindingFactors = userResult.credentialSecretsBlindingFactors; + + Map userCredentialInfo = new HashMap<>(); + userCredentialInfo.put(ParamKeyConstant.MASTER_SECRET, masterSecret); + userCredentialInfo.put(ParamKeyConstant.BLINDING_FACTORS, credentialSecretsBlindingFactors); + String json = DataToolUtils.serialize(userCredentialInfo); + String id = new StringBuffer().append(weIdAuthentication.getWeId()).append("_") + .append(cptId).toString(); + //String id=(String)preCredential.getClaim().get(CredentialConstant.CREDENTIAL_META_KEY_ID); + + //save masterSecret and credentialSecretsBlindingFactors to persistence. + ResponseData dbResp = getDataDriver() + .addOrUpdate(DataDriverConstant.DOMAIN_USER_MASTER_SECRET, id, json); + if (dbResp.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[makeCredential] save masterSecret and blindingFactors to db failed."); + return null; + } + + return userResult; + } + + /** + * build credentialInfoMap from pre-credential and claim sent by issuer. + */ + private static Map buildCredentialInfo(CredentialPojo preCredential, + String claimJson) { + + CredentialPojo tempCredential = DataToolUtils.clone(preCredential); + Map claim = preCredential.getClaim(); + Map credentialInfo = new HashMap(); + Map newCredentialInfo = new HashMap(); + try { + Map claimMap = DataToolUtils.deserialize(claimJson, HashMap.class); + tempCredential.setClaim(claimMap); + tempCredential.setContext( + String.valueOf(claim.get(CredentialConstant.CREDENTIAL_META_KEY_CONTEXT))); + tempCredential + .setCptId((Integer) claim.get(CredentialConstant.CREDENTIAL_META_KEY_CPTID)); + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp( + (Long) (claim.get(CredentialConstant.CREDENTIAL_META_KEY_EXPIRATIONDATE))); + tempCredential.setExpirationDate(newExpirationDate); + tempCredential + .setId(String.valueOf(claim.get(CredentialConstant.CREDENTIAL_META_KEY_ID))); + Long newIssuanceDate = + DateUtils.convertToNoMillisecondTimeStamp( + (Long) (claim.get(CredentialConstant.CREDENTIAL_META_KEY_ISSUANCEDATE))); + tempCredential.setIssuanceDate(newIssuanceDate); + tempCredential.setIssuer( + String.valueOf(claim.get(CredentialConstant.CREDENTIAL_META_KEY_ISSUER))); + credentialInfo = JsonUtil.credentialToMonolayer(tempCredential); + for (Map.Entry entry : credentialInfo.entrySet()) { + newCredentialInfo.put(entry.getKey(), String.valueOf(entry.getValue())); + } + } catch (IOException e) { + logger.error("[buildCredentialInfo] build credential info map failed.", e); + } + return newCredentialInfo; + } + + private static void processZkpPolicy( + ClaimPolicy claimPolicy, + List revealedAttributeList, + List predicateList) { + + String policyJson = null; + try { + policyJson = JsonUtil.claimPolicyToMonolayer(claimPolicy); + } catch (IOException e) { + e.printStackTrace(); + } + Map disclosureMap = DataToolUtils + .deserialize(policyJson, HashMap.class); + for (Map.Entry entry : disclosureMap.entrySet()) { + + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof Map) { + processExpression(key, (HashMap) value, predicateList); + } else if (value instanceof Integer) { + processBaseValue(key, String.valueOf(value), revealedAttributeList); + } else if (value instanceof String) { + processBaseValue(key, (String) value, revealedAttributeList); + } else { + return; + } + } + + } + + private static void processExpression( + String key, + Map expression, + List predicateList) { + + for (Map.Entry entry : expression.entrySet()) { + + String predicateKey = entry.getKey(); + Object predicateValue = entry.getValue(); + PredicateType predicateType = getPredicateType(predicateKey); + Predicate predicate = Utils.makePredicate(key, predicateType, (Integer) predicateValue); + predicateList.add(predicate); + } + } + + private static void processBaseValue( + String key, + String value, + List revealedAttributeList) { + if (StringUtils.equals(value, DISCLOSED)) { + revealedAttributeList.add(key); + } + } + + private static PredicateType getPredicateType(String predicate) { + + switch (predicate) { + case "EQ": + return PredicateType.EQ; + case "GE": + return PredicateType.GE; + case "GT": + return PredicateType.GT; + case "LE": + return PredicateType.LE; + case "LT": + return PredicateType.LT; + default: + return null; + + } + } + + private static ResponseData verifyLiteCredential( + CredentialPojo credential, + String publicKey, + String methodId) { + // Lite Credential only contains limited areas (others truncated) + if (credential.getCptId() == null || credential.getCptId().intValue() < 0) { + return new ResponseData<>(false, ErrorCode.CPT_ID_ILLEGAL); + } + if (!WeIdUtils.isWeIdValid(credential.getIssuer())) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_ISSUER_INVALID); + } + if (credential.getClaim() == null || credential.getClaim().size() == 0) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS); + } + if (credential.getProof() == null || StringUtils.isEmpty(credential.getSignature())) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_SIGNATURE_NOT_EXISTS); + } + String rawData = CredentialPojoUtils.getLiteCredentialThumbprintWithoutSig(credential); + + // Using provided public key to verify signature + if (!StringUtils.isBlank(publicKey)) { + boolean result; + try { + // For Lite CredentialPojo, we begin to use Secp256k1 verify to fit external type + result = DataToolUtils.verifySignature(rawData, credential.getSignature(), new BigInteger(publicKey)); + } catch (Exception e) { + logger.error("[verifyContent] verify signature fail.", e); + return new ResponseData(false, ErrorCode.CREDENTIAL_SIGNATURE_BROKEN); + } + if (!result) { + return new ResponseData(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + // No existing public key hence go chain + String issuerWeid = credential.getIssuer(); + // Fetch public key from chain + ResponseData innerResponseData = + getWeIdService().getWeIdDocument(issuerWeid); + if (innerResponseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "Error occurred when fetching WeIdentity DID document for: {}, msg: {}", + issuerWeid, innerResponseData.getErrorMessage()); + return new ResponseData(false, + ErrorCode.getTypeByErrorCode(innerResponseData.getErrorCode())); + } else { + WeIdDocument weIdDocument = innerResponseData.getResult(); + ErrorCode verifyErrorCode = DataToolUtils.verifySignatureFromWeId( + rawData, credential.getSignature(), weIdDocument, methodId); + if (verifyErrorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData(false, verifyErrorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + + } + } + + /** + * Verify the authorization info in an authorization token credential. + * + * @param authInfo the auth info in CPT101 format + * @return success if valid, specific error codes otherwise + */ + public static ErrorCode verifyAuthInfo(Cpt101 authInfo) { + if (authInfo == null) { + return ErrorCode.ILLEGAL_INPUT; + } + + String serviceUrl = authInfo.getServiceUrl(); + String resourceId = authInfo.getResourceId(); + Long duration = authInfo.getDuration(); + if (!CredentialUtils.isValidUuid(resourceId)) { + logger.error("Resource ID illegal: is not a valid UUID."); + return ErrorCode.ILLEGAL_INPUT; + } + if (!DataToolUtils.isValidEndpointUrl(serviceUrl)) { + logger.error("Service URL illegal."); + return ErrorCode.ILLEGAL_INPUT; + } + if (duration < 0) { + logger.error("Auth token duration of validity illegal: already expired."); + return ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL; + } + + String fromWeId = authInfo.getFromWeId(); + String toWeId = authInfo.getToWeId(); + if (fromWeId.equalsIgnoreCase(toWeId)) { + logger.error("FromWeId and ToWeId must be different."); + return ErrorCode.AUTHORIZATION_FROM_TO_MUST_BE_DIFFERENT; + } + ResponseData existResp = getWeIdService().isWeIdExist(fromWeId); + if (!existResp.getResult()) { + logger.error("From WeID illegal: {}", existResp.getErrorMessage()); + return ErrorCode.getTypeByErrorCode(existResp.getErrorCode()); + } + existResp = getWeIdService().isWeIdExist(toWeId); + if (!existResp.getResult()) { + logger.error("To WeID illegal: {}", existResp.getErrorMessage()); + return ErrorCode.getTypeByErrorCode(existResp.getErrorCode()); + } + return ErrorCode.SUCCESS; + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#createCredential( + * com.webank.weid.protocol.request.CreateCredentialPojoArgs + * ) + */ + @Override + public ResponseData createCredential(CreateCredentialPojoArgs args) { + + try { + ErrorCode innerResponseData = + CredentialPojoUtils.isCreateCredentialPojoArgsValid(args); + if (ErrorCode.SUCCESS.getCode() != innerResponseData.getCode()) { + logger.error("Create Credential Args illegal: {}", + innerResponseData.getCodeDesc()); + return new ResponseData<>(null, innerResponseData); + } + CredentialPojo result = new CredentialPojo(); + String context = CredentialUtils.getDefaultCredentialContext(); + result.setContext(context); + if (StringUtils.isBlank(args.getId())) { + result.setId(UUID.randomUUID().toString()); + } else { + result.setId(args.getId()); + } + result.setCptId(args.getCptId()); + Long issuanceDate = args.getIssuanceDate(); + if (issuanceDate == null) { + result.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + } else { + Long newIssuanceDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getIssuanceDate()); + if (newIssuanceDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL); + } else { + result.setIssuanceDate(newIssuanceDate); + } + } + // Comment these lines out since we now support multi-public-keys in WeID document + // if (!WeIdUtils.validatePrivateKeyWeIdMatches( + // args.getWeIdAuthentication().getWeIdPrivateKey(), + // args.getIssuer())) { + // logger.error("Create Credential, private key does not match the current weid."); + // return new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + // } + result.setIssuer(args.getIssuer()); + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getExpirationDate()); + if (newExpirationDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + } else { + result.setExpirationDate(newExpirationDate); + } + result.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + result.addType(args.getType().getName()); + + Object claimObject = args.getClaim(); + String claimStr = null; + if (!(claimObject instanceof String)) { + claimStr = DataToolUtils.serialize(claimObject); + } else { + claimStr = (String) claimObject; + } + + HashMap claimMap = DataToolUtils.deserialize(claimStr, HashMap.class); + result.setClaim(claimMap); + + String privateKey = args.getWeIdAuthentication().getWeIdPrivateKey().getPrivateKey(); + if (StringUtils.equals(args.getType().getName(), CredentialType.LITE1.getName())) { + return createLiteCredential(result, privateKey); + } + + Map saltMap = DataToolUtils.clone(claimMap); + generateSalt(saltMap, null); + String rawData = CredentialPojoUtils + .getCredentialThumbprintWithoutSig(result, saltMap, null); + + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + result.putProofValue(ParamKeyConstant.PROOF_CREATED, result.getIssuanceDate()); + + String creator = args.getWeIdAuthentication().getWeId(); + result.putProofValue(ParamKeyConstant.PROOF_CREATOR, creator); + //TODO:目前CredentialProofType只有ECDSA类型,需要添加SM2 + String proofType = CredentialProofType.ECDSA.getTypeName(); + result.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + result.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + result.setSalt(saltMap); + ResponseData responseData = new ResponseData<>( + result, + ErrorCode.SUCCESS + ); + + return responseData; + } catch (Exception e) { + logger.error("Generate Credential failed due to system error. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); + } + } + + private ResponseData createLiteCredential(CredentialPojo credentialPojo, + String privateKey) { + + String rawData = CredentialPojoUtils.getLiteCredentialThumbprintWithoutSig(credentialPojo); + + // For Lite CredentialPojo, we begin to use Secp256k1 format signature to fit external type + //替换国密 + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey, 10)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + String proofType = CredentialProofType.ECDSA.getTypeName(); + credentialPojo.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + credentialPojo.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + ResponseData responseData = new ResponseData<>( + credentialPojo, + ErrorCode.SUCCESS + ); + return responseData; + } + + /** + * Add an extra signer and signature to a Credential. Multiple signatures will be appended in an + * embedded manner. + * + * @param credentialList original credential list + * @param callerAuth the passed-in privateKey and WeID bundle to sign + * @return the modified CredentialWrapper + */ + @Override + public ResponseData addSignature( + List credentialList, + WeIdAuthentication callerAuth) { + if (credentialList == null || credentialList.size() == 0 + || CredentialPojoUtils.isWeIdAuthenticationValid(callerAuth) != ErrorCode.SUCCESS) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + CredentialPojo result = new CredentialPojo(); + result.setCptId(CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT); + result.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + result.setId(UUID.randomUUID().toString()); + result.setContext(CredentialUtils.getDefaultCredentialContext()); + Long expirationDate = 0L; + for (CredentialPojo arg : credentialList) { + if (arg.getExpirationDate() > expirationDate) { + expirationDate = arg.getExpirationDate(); + } + } + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp(expirationDate); + if (newExpirationDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + } else { + result.setExpirationDate(newExpirationDate); + } + // Comment these lines out since we now support multi-public-keys + // if (!WeIdUtils.validatePrivateKeyWeIdMatches( + // callerAuth.getWeIdPrivateKey(), + // callerAuth.getWeId())) { + // logger.error("Create Credential, private key does not match the current weid."); + // return new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + // } + if (!getWeIdService().isWeIdExist(callerAuth.getWeId()).getResult()) { + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + String privateKey = callerAuth.getWeIdPrivateKey().getPrivateKey(); + // CryptoKeyPair 无需适配v3,只需要提取里面的地址 + String address = DataToolUtils.addressFromPrivate(new BigInteger(privateKey)); + String keyWeId = WeIdUtils.convertAddressToWeId(address); + result.setIssuer(keyWeId); + result.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + + List trimmedCredentialMapList = trimCredentialList(credentialList); + + // The claim will be the wrapper of the to-be-signed credentialpojos + HashMap claim = new HashMap<>(); + claim.put("credentialList", trimmedCredentialMapList); + result.setClaim(claim); + + // For embedded signature, salt here is totally meaningless - hence we left it blank + Map saltMap = DataToolUtils.clone(claim); + CredentialPojoUtils.clearMap(saltMap); + String rawData = CredentialPojoUtils + .getEmbeddedCredentialThumbprintWithoutSig(credentialList); + //替换国密 + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + result.putProofValue(ParamKeyConstant.PROOF_CREATED, result.getIssuanceDate()); + + String creator = callerAuth.getWeId(); + result.putProofValue(ParamKeyConstant.PROOF_CREATOR, creator); + + String proofType = CredentialProofType.ECDSA.getTypeName(); + result.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + result.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + result.setSalt(saltMap); + + return new ResponseData<>(result, ErrorCode.SUCCESS); + } + + private List trimCredentialList(List credentialList) { + List trimmedCredentialList = new ArrayList<>(); + for (CredentialPojo arg : credentialList) { + boolean found = false; + for (CredentialPojo credAlive : trimmedCredentialList) { + if (CredentialPojoUtils.isEqual(arg, credAlive)) { + found = true; + break; + } + } + if (!found) { + ErrorCode errorCode = CredentialPojoUtils.isCredentialPojoValid(arg); + if (errorCode != ErrorCode.SUCCESS) { + return null; + } + trimmedCredentialList.add(arg); + } + } + + List trimmedCredentialMapList = new ArrayList<>(); + for (CredentialPojo credAlive : trimmedCredentialList) { + try { + trimmedCredentialMapList.add(DataToolUtils.objToMap(credAlive)); + } catch (Exception e) { + logger.error("Failed to convert Credential to map structure.", e); + return null; + } + } + return trimmedCredentialMapList; + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#createSelectiveCredential( + * com.webank.weid.protocol.base.CredentialPojo, + * com.webank.weid.protocol.base.ClaimPolicy + * ) + */ + @Override + public ResponseData createSelectiveCredential( + CredentialPojo credential, + ClaimPolicy claimPolicy) { + + if (credential == null) { + logger.error("[createSelectiveCredential] input credential is null"); + return new ResponseData(null, ErrorCode.ILLEGAL_INPUT); + } + if (credential.getType() != null + && (credential.getType().contains(CredentialType.LITE1.getName()) + || credential.getType().contains(CredentialType.ZKP.getName()))) { + logger.error( + "[createSelectiveCredential] Lite Credential and ZKP Credential DO NOT support " + + "this function(createSelectiveCredential), type = {}.", credential.getType()); + return new ResponseData(null, + ErrorCode.CREDENTIAL_NOT_SUPPORT_SELECTIVE_DISCLOSURE); + } + try { + CredentialPojo credentialClone = DataToolUtils.clone(credential); + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialClone); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return new ResponseData(null, checkResp); + } + if (credentialClone.getCptId() + .equals(CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT)) { + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + if (claimPolicy == null) { + logger.error("[createSelectiveCredential] claimPolicy is null."); + return new ResponseData(null, + ErrorCode.CREDENTIAL_CLAIM_POLICY_NOT_EXIST); + } + if (CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt())) { + return new ResponseData(null, ErrorCode.CREDENTIAL_RE_DISCLOSED); + } + String disclosure = claimPolicy.getFieldsToBeDisclosed(); + Map saltMap = credentialClone.getSalt(); + Map claim = credentialClone.getClaim(); + + Map disclosureMap = DataToolUtils + .deserialize(disclosure, HashMap.class); + + if (!validCredentialMapArgs(claim, saltMap, disclosureMap)) { + logger.error( + "[createSelectiveCredential] create failed. message is {}", + ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCodeDesc() + ); + return new ResponseData(null, + ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM); + } + // 补 policy + addKeyToPolicy(disclosureMap, claim); + // 加盐处理 + addSelectSalt(disclosureMap, saltMap, claim, false); + credentialClone.setSalt(saltMap); + + ResponseData response = new ResponseData(); + response.setResult(credentialClone); + response.setErrorCode(ErrorCode.SUCCESS); + return response; + } catch (DataTypeCastException e) { + logger.error("Generate SelectiveCredential failed, " + + "credential disclosure data type illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL); + } catch (WeIdBaseException e) { + logger.error("Generate SelectiveCredential failed, " + + "policy disclosurevalue illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL); + } catch (Exception e) { + logger.error("Generate SelectiveCredential failed due to system error. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); + } + } + + /** + * Get the full hash value of a CredentialPojo. All fields in the CredentialPojo will be + * included. This method should be called when creating and verifying the Credential Evidence + * and the result is selectively-disclosure irrelevant. + * + * @param credentialPojo the args + * @return the Credential Hash value + */ + @Override + public ResponseData getCredentialPojoHash(CredentialPojo credentialPojo) { + ErrorCode innerResponse = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { + logger.error("Create Evidence input format error!"); + return new ResponseData<>(StringUtils.EMPTY, innerResponse); + } + return new ResponseData<>(CredentialPojoUtils.getCredentialPojoHash(credentialPojo, null), + ErrorCode.SUCCESS); + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#verify( + * java.lang.String, + * com.webank.weid.protocol.base.CredentialPojo + * ) + */ + @Override + public ResponseData verify(String issuerWeId, CredentialPojo credential) { + + if (credential == null) { + logger.error("[verify] The input credential is invalid."); + return new ResponseData(false, ErrorCode.ILLEGAL_INPUT); + } + + if (isZkpCredential(credential)) { + return verifyZkpCredential(credential); + } + + String issuerId = credential.getIssuer(); + if (!StringUtils.equals(issuerWeId, issuerId)) { + logger.error("[verify] The input issuer weid is not match the credential's."); + return new ResponseData(false, ErrorCode.CREDENTIAL_ISSUER_MISMATCH); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, null, null); + } + ErrorCode errorCode = verifyContent(credential, null, false, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] credential verify failed. error message :{}", errorCode); + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#verify( + * com.webank.weid.protocol.base.CredentialPojo, + * com.webank.weid.protocol.base.WeIdPublicKey + * ) + */ + @Override + public ResponseData verify( + WeIdPublicKey issuerPublicKey, + CredentialPojo credential) { + + String publicKey = issuerPublicKey.getPublicKey(); + if (StringUtils.isEmpty(publicKey)) { + return new ResponseData(false, ErrorCode.CREDENTIAL_PUBLIC_KEY_NOT_EXISTS); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, issuerPublicKey.getPublicKey(), null); + } + ErrorCode errorCode = verifyContent(credential, publicKey, false, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#verify( + * java.lang.String, + * com.webank.weid.protocol.base.PresentationPolicyE, + * com.webank.weid.protocol.base.Challenge, + * com.webank.weid.protocol.base.PresentationE + * ) + */ + @Override + public ResponseData verify( + String presenterWeId, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + PresentationE presentationE) { + + List typeList = presentationE.getType(); + if (typeList.contains(CredentialConstant.PRESENTATION_PDF)) { + logger.error("[verify] please use verifyPresentationFromPDF function."); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_USE_VERIFY_FUNCTION_ERROR); + } + + ErrorCode errorCode = + checkInputArgs(presenterWeId, presentationPolicyE, challenge, presentationE); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] checkInputArgs fail."); + return new ResponseData(false, errorCode); + } + + //verify cptId of presentationE + List credentialList = presentationE.getVerifiableCredential(); + Map policyMap = presentationPolicyE.getPolicy(); + ErrorCode verifyCptIdresult = + this.verifyCptId(policyMap, credentialList); + if (verifyCptIdresult.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] verify cptId failed."); + return new ResponseData(false, verifyCptIdresult); + } + try { + for (CredentialPojo credential : credentialList) { + //verify policy + Integer cptId = credential.getCptId(); + ClaimPolicy claimPolicy = policyMap.get(cptId); + if (claimPolicy != null) { + ErrorCode verifypolicyResult = this + .verifyPolicy(credential, claimPolicy, presenterWeId); + if (verifypolicyResult.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] verify policy {} failed.", policyMap); + return new ResponseData(false, verifypolicyResult); + } + } + //verify credential + if (isZkpCredential(credential)) { + return verifyZkpCredential(credential); + + } + ErrorCode verifyCredentialResult = verifyContent(credential, null, false, null); + if (verifyCredentialResult.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[verify] verify credential {} failed.", credential); + return new ResponseData(false, verifyCredentialResult); + } + } + return new ResponseData(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error( + "[verify] verify credential error.", e); + return new ResponseData(false, ErrorCode.UNKNOW_ERROR); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#verify() + */ + @Override + public ResponseData verify( + String issuerWeId, + String methodId, + CredentialPojo credential + ) { + if (credential == null) { + logger.error("[verify] The input credential is invalid."); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if (isZkpCredential(credential)) { + return verifyZkpCredential(credential); + } + String issuerId = credential.getIssuer(); + if (!StringUtils.equals(issuerWeId, issuerId)) { + logger.error("[verify] The input issuer weid is not match the credential's."); + return new ResponseData(false, ErrorCode.CREDENTIAL_ISSUER_MISMATCH); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, null, methodId); + } + ErrorCode errorCode = verifyContent(credential, null, false, methodId); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[verify] credential verify failed. error message :{}", errorCode); + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#verify( + * com.webank.weid.protocol.base.CredentialPojo, + * com.webank.weid.protocol.base.WeIdPublicKey + * ) + */ + @Override + public ResponseData verifyOffline( + WeIdPublicKey issuerPublicKey, + CredentialPojo credential) { + + String publicKey = issuerPublicKey.getPublicKey(); + if (StringUtils.isEmpty(publicKey)) { + return new ResponseData(false, ErrorCode.CREDENTIAL_PUBLIC_KEY_NOT_EXISTS); + } + if (CredentialPojoUtils.isLiteCredential(credential)) { + return verifyLiteCredential(credential, issuerPublicKey.getPublicKey(), null); + } + ErrorCode errorCode = verifyContent(credential, publicKey, true, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData(false, errorCode); + } + return new ResponseData(true, ErrorCode.SUCCESS); + } + + /*@Override + public ResponseData verifyPresentationFromPdf( + String pdfTemplatePath, + byte[] serializePdf, + String presenterWeId, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + PresentationE presentationE) { + + //verify pdf + PdfAttributeInfo pdfAttributeInfo = getPdfTransportation().getBaseData(serializePdf); + if (pdfAttributeInfo == null) { + logger.error("[verifyPresentationFromPDF] get pdf base data error."); + } + Boolean retVerifyPdf = getPdfTransportation().verifyPdf( + presentationE, + pdfTemplatePath, + pdfAttributeInfo, + serializePdf + ); + + if (!retVerifyPdf) { + logger.error("[verifyPresentationFromPDF] verify pdf error."); + return new ResponseData<>(false, ErrorCode.TRANSPORTATION_PDF_VERIFY_ERROR); + } + + List typeList = presentationE.getType(); + if (typeList.contains(CredentialConstant.PRESENTATION_PDF)) { + typeList.remove(CredentialConstant.PRESENTATION_PDF); + } + presentationE.setType(typeList); + + return this.verify(presenterWeId, presentationPolicyE, challenge, presentationE); + }*/ + + private ErrorCode checkInputArgs( + String presenterWeId, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + PresentationE presentationE) { + + if (StringUtils.isBlank(presenterWeId) + || challenge == null + || StringUtils.isBlank(challenge.getNonce()) + || !CredentialPojoUtils.checkPresentationPolicyEValid(presentationPolicyE)) { + logger.error("[verify] presentation verify failed, please check your input."); + return ErrorCode.ILLEGAL_INPUT; + } + + ErrorCode errorCode = CredentialPojoUtils.checkPresentationEValid(presentationE); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[verify] presentation verify failed, error message : {}", + errorCode.getCodeDesc() + ); + return errorCode; + } + + //verify presenterWeId + if (StringUtils.isNotBlank(challenge.getWeId()) + && !presenterWeId.equals(challenge.getWeId())) { + logger.error("[verify] The input issuer weid is not match the presentian's."); + return ErrorCode.CREDENTIAL_PRESENTERWEID_NOTMATCH; + } + + //verify challenge + if (!challenge.getNonce().equals(presentationE.getNonce())) { + logger + .error("[verify] The nonce of challenge is not matched with the presentationE's."); + return ErrorCode.PRESENTATION_CHALLENGE_NONCE_MISMATCH; + } + + //verify Signature of PresentationE + WeIdDocument weIdDocument = getWeIdService().getWeIdDocument(presenterWeId).getResult(); + if (weIdDocument == null) { + logger.error( + "[verify]presentation verify failed, because the presenter weid :{} " + + "does not exist.", + presenterWeId); + return ErrorCode.WEID_DOES_NOT_EXIST; + } + String signature = presentationE.getSignature(); + errorCode = + DataToolUtils + .verifySignatureFromWeId(presentationE.toRawData(), signature, + weIdDocument, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return ErrorCode.PRESENTATION_SIGNATURE_MISMATCH; + } + return ErrorCode.SUCCESS; + } + + private ErrorCode verifyCptId( + Map policyMap, + List credentialList) { + + if (policyMap.size() > credentialList.size()) { + return ErrorCode.CREDENTIAL_CPTID_NOTMATCH; + } else { + for (CredentialPojo credential : credentialList) { + if (isZkpCredential(credential)) { + continue; + } else { + Integer cptId = credential.getCptId(); + if (cptId == null || !policyMap.containsKey(cptId)) { + return ErrorCode.CREDENTIAL_CPTID_NOTMATCH; + } + } + } + } + return ErrorCode.SUCCESS; + } + + private ErrorCode verifyDisclosureAndSalt( + Map disclosureMap, + Map saltMap) { + + for (String disclosureK : disclosureMap.keySet()) { + Object disclosureV = disclosureMap.get(disclosureK); + Object saltV = saltMap.get(disclosureK); + if (disclosureV instanceof Map) { + ErrorCode code = verifyDisclosureAndSalt((HashMap) disclosureV, (HashMap) saltV); + if (code.getCode() != ErrorCode.SUCCESS.getCode()) { + return code; + } + } else if (disclosureV instanceof List) { + ArrayList disclosurs = (ArrayList) disclosureV; + ErrorCode code = verifyDisclosureAndSaltList(disclosurs, (ArrayList) saltV); + if (code.getCode() != ErrorCode.SUCCESS.getCode()) { + return code; + } + } else { + String disclosure = String.valueOf(disclosureV); + + if (saltV == null + || (!disclosure.equals(NOT_DISCLOSED) && !disclosure.equals(DISCLOSED) + && !disclosure.equals(EXISTED))) { + logger.error( + "[verifyDisclosureAndSalt] policy disclosureValue {} illegal.", + disclosureMap + ); + return ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL; + } + + String salt = String.valueOf(saltV); + if ((disclosure.equals(NOT_DISCLOSED) && salt.length() > 1) + || (disclosure.equals(NOT_DISCLOSED) && !salt.equals(NOT_DISCLOSED))) { + return ErrorCode.CREDENTIAL_DISCLOSUREVALUE_NOTMATCH_SALTVALUE; + } + + if (disclosure.equals(DISCLOSED) && salt.length() <= 1) { + return ErrorCode.CREDENTIAL_DISCLOSUREVALUE_NOTMATCH_SALTVALUE; + } + } + } + return ErrorCode.SUCCESS; + } + + private ErrorCode verifyDisclosureAndSaltList( + List disclosureList, + List saltList + ) { + for (int i = 0; i < disclosureList.size(); i++) { + Object disclosure = disclosureList.get(i); + Object saltV = saltList.get(i); + if (disclosure instanceof Map) { + ErrorCode code = + verifyDisclosureAndSaltList( + (HashMap) disclosure, + (ArrayList) saltList + ); + if (code.getCode() != ErrorCode.SUCCESS.getCode()) { + return code; + } + } else if (disclosure instanceof List) { + ErrorCode code = + verifyDisclosureAndSaltList( + (ArrayList) disclosure, + (ArrayList) saltV + ); + if (code.getCode() != ErrorCode.SUCCESS.getCode()) { + return code; + } + } + } + return ErrorCode.SUCCESS; + } + + private ErrorCode verifyDisclosureAndSaltList( + Map disclosure, + List saltList + ) { + for (int i = 0; i < saltList.size(); i++) { + Object saltV = saltList.get(i); + ErrorCode code = verifyDisclosureAndSalt((HashMap) disclosure, (HashMap) saltV); + if (code.getCode() != ErrorCode.SUCCESS.getCode()) { + return code; + } + } + return ErrorCode.SUCCESS; + } + + private ErrorCode verifyPolicy(CredentialPojo credentialPojo, ClaimPolicy claimPolicy, + String presenterWeId) { + if (isZkpCredential(credentialPojo)) { + return ErrorCode.SUCCESS; + } + Map saltMap = credentialPojo.getSalt(); + String disclosure = claimPolicy.getFieldsToBeDisclosed(); + Map disclosureMap = DataToolUtils.deserialize(disclosure, HashMap.class); + + Object idValue = disclosureMap.get("id"); + if (idValue != null) { + Object weid = credentialPojo.getClaim().get("id"); + if (StringUtils.equals(String.valueOf(idValue), DISCLOSED)) { + if (!StringUtils.equals(String.valueOf(weid), presenterWeId)) { + logger.error( + "[verifyPolicy] the presenter weid->{} of presentation does not " + + "match the credential's ->{}. ", + presenterWeId, + weid); + return ErrorCode.PRESENTATION_WEID_CREDENTIAL_WEID_MISMATCH; + } + } else if (StringUtils.equals(String.valueOf(idValue), EXISTED) + && !credentialPojo.getClaim().containsKey("id")) { + logger.error( + "[verifyPolicy] the presenter weid->{} of presentation does not " + + "match the credential's ->{}. ", + presenterWeId, + weid); + return ErrorCode.PRESENTATION_CREDENTIAL_CLAIM_WEID_NOT_EXIST; + } + } + return this.verifyDisclosureAndSalt(disclosureMap, saltMap); + } + + @Override + public ResponseData createPresentation( + List credentialList, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + WeIdAuthentication weIdAuthentication) { + + PresentationE presentation = new PresentationE(); + try { + // 检查输入数据完整性 + ErrorCode errorCode = + validateCreateArgs( + credentialList, + presentationPolicyE, + challenge, + weIdAuthentication + ); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "check input error:{}-{}", + errorCode.getCode(), + errorCode.getCodeDesc() + ); + return new ResponseData(null, errorCode); + } + // 处理credentialList数据 + errorCode = processCredentialList(credentialList, presentationPolicyE, presentation, + weIdAuthentication.getWeId()); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "process credentialList error:{}-{}", + errorCode.getCode(), + errorCode.getCodeDesc() + ); + return new ResponseData(null, errorCode); + } + presentation.getContext().add(CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT); + presentation.getType().add(WeIdConstant.DEFAULT_PRESENTATION_TYPE); + // 处理proof数据 + generatePresentationProof(challenge, weIdAuthentication, presentation); + return new ResponseData(presentation, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("create PresentationE error", e); + return new ResponseData(null, ErrorCode.UNKNOW_ERROR); + } + } + + private ErrorCode validateCreateArgs( + List credentialList, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + WeIdAuthentication weIdAuthentication) { + + if (challenge == null || weIdAuthentication == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (StringUtils.isBlank(challenge.getNonce()) + || challenge.getVersion() == null) { + return ErrorCode.PRESENTATION_CHALLENGE_INVALID; + } + if (weIdAuthentication.getWeIdPrivateKey() == null + || !WeIdUtils.validatePrivateKeyWeIdMatches( + weIdAuthentication.getWeIdPrivateKey(), weIdAuthentication.getWeId())) { + return ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH; + } + if (!StringUtils.isBlank(challenge.getWeId()) + && !challenge.getWeId().equals(weIdAuthentication.getWeId())) { + return ErrorCode.PRESENTATION_CHALLENGE_WEID_MISMATCH; + } + if (StringUtils.isBlank(weIdAuthentication.getAuthenticationMethodId())) { + return ErrorCode.PRESENTATION_AUTHENTICATION_METHOD_ID_INVALID; + } + return validateClaimPolicy(credentialList, presentationPolicyE); + } + + private ErrorCode validateClaimPolicy( + List credentialList, + PresentationPolicyE presentationPolicyE) { + if (CollectionUtils.isEmpty(credentialList)) { + return ErrorCode.ILLEGAL_INPUT; + } + if (presentationPolicyE == null || presentationPolicyE.getPolicy() == null) { + return ErrorCode.PRESENTATION_POLICY_INVALID; + } + if (!WeIdUtils.isWeIdValid(presentationPolicyE.getPolicyPublisherWeId())) { + return ErrorCode.PRESENTATION_POLICY_PUBLISHER_WEID_INVALID; + } + ResponseData weIdRes = getWeIdService() + .isWeIdExist(presentationPolicyE.getPolicyPublisherWeId()); + if (ErrorCode.SUCCESS.getCode() != weIdRes.getErrorCode() || !weIdRes.getResult()) { + return ErrorCode.PRESENTATION_POLICY_PUBLISHER_WEID_NOT_EXIST; + } + for (CredentialPojo credentialPojo : credentialList) { + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialPojo); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return checkResp; + } + } + List cptIdList = credentialList.stream().map( + cpwl -> cpwl.getCptId()).collect(Collectors.toList()); + Set claimPolicyCptSet = presentationPolicyE.getPolicy().keySet(); + if (!cptIdList.containsAll(claimPolicyCptSet)) { + return ErrorCode.PRESENTATION_CREDENTIALLIST_MISMATCH_CLAIM_POLICY; + } + return ErrorCode.SUCCESS; + } + + private ErrorCode processCredentialList( + List credentialList, + PresentationPolicyE presentationPolicy, + PresentationE presentation, + String userId) { + + List newCredentialList = new ArrayList<>(); + // 获取ClaimPolicyMap + Map claimPolicyMap = presentationPolicy.getPolicy(); + + String policyType = presentationPolicy.getPolicyType(); + //如果presentationPolicy是ZKP类型,则所有credentials采用ZKP生成 + if (StringUtils.equals(policyType, CredentialType.ZKP.getName())) { + newCredentialList = generateZkpCredentialList(credentialList, presentationPolicy, + userId); + } else { + // 如果presentationPolicy是普通的类型,则所有credentials采用基于hash链接的选择性披露 + // 遍历所有原始证书 + for (CredentialPojo credential : credentialList) { + // 根据原始证书获取对应的 claimPolicy + ClaimPolicy claimPolicy = claimPolicyMap.get(credential.getCptId()); + if (claimPolicy == null) { + continue; + } + // 根据原始证书和claimPolicy去创建选择性披露凭证 + ResponseData res = + this.createSelectiveCredential(credential, claimPolicy); + if (res.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + return ErrorCode.getTypeByErrorCode(res.getErrorCode().intValue()); + } + newCredentialList.add(res.getResult()); + } + } + + presentation.setVerifiableCredential(newCredentialList); + return ErrorCode.SUCCESS; + } + + private List generateZkpCredentialList( + List credentialList, + PresentationPolicyE presentationPolicy, + String userId) { + + List newCredentialList = new ArrayList<>(); + // 获取ClaimPolicyMap + Map claimPolicyMap = presentationPolicy.getPolicy(); + for (CredentialPojo credential : credentialList) { + // 根据原始证书获取对应的 claimPolicy + ClaimPolicy claimPolicy = claimPolicyMap.get(credential.getCptId()); + if (claimPolicy == null) { + continue; + } + // 根据原始证书和claimPolicy去创建ZKP类型选择性披露凭证 + ResponseData res = this + .createZkpCredential(credential, claimPolicy, userId); + + if (res.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + return null; + } + newCredentialList.add(res.getResult()); + } + + return newCredentialList; + } + + private void generatePresentationProof( + Challenge challenge, + WeIdAuthentication weIdAuthentication, + PresentationE presentation) { + + String proofType = CredentialProofType.ECDSA.getTypeName(); + presentation.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + + Long proofCreated = DateUtils.getNoMillisecondTimeStamp(); + presentation.putProofValue(ParamKeyConstant.PROOF_CREATED, proofCreated); + + String methodId = weIdAuthentication.getAuthenticationMethodId(); + presentation.putProofValue(ParamKeyConstant.PROOF_VERIFICATION_METHOD_ID, methodId); + presentation.putProofValue(ParamKeyConstant.PROOF_NONCE, challenge.getNonce()); + /*String signature = + DataToolUtils.secp256k1Sign( + presentation.toRawData(), + new BigInteger(weIdAuthentication.getWeIdPrivateKey().getPrivateKey()) + );*/ + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(presentation.toRawData(), weIdAuthentication.getWeIdPrivateKey().getPrivateKey()) + );; + presentation.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + } + + /** + * Create a trusted timestamp credential. + * + * @param credentialList the credentialPojo list to be signed + * @param weIdAuthentication the caller authentication + * @return the embedded timestamp in credentialPojo + */ + @Override + public ResponseData createTrustedTimestamp( + List credentialList, + WeIdAuthentication weIdAuthentication) { + if (credentialList == null || credentialList.size() == 0 + || CredentialPojoUtils.isWeIdAuthenticationValid(weIdAuthentication) + != ErrorCode.SUCCESS) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + + // For business reasons, we do not allow a selectively disclosed credential to be stamped. + if (CredentialPojoUtils.isSelectivelyDisclosedCredentialList(credentialList)) { + return new ResponseData<>(null, + ErrorCode.TIMESTAMP_CREATION_FAILED_FOR_SELECTIVELY_DISCLOSED); + } + + CredentialPojo credential = new CredentialPojo(); + credential.setCptId(CredentialConstant.EMBEDDED_TIMESTAMP_CPT); + String privateKey = weIdAuthentication.getWeIdPrivateKey().getPrivateKey(); + String keyWeId = WeIdUtils.convertAddressToWeId(DataToolUtils.addressFromPrivate(new BigInteger(privateKey))); + credential.setIssuer(keyWeId); + credential.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + credential.setId(UUID.randomUUID().toString()); + credential.setContext(CredentialUtils.getDefaultCredentialContext()); + // WeSign default valid: 1 year + credential.setExpirationDate(DateUtils.getNoMillisecondTimeStamp() + 31536000L); + credential.addType(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + + String rawData = CredentialPojoUtils + .getEmbeddedCredentialThumbprintWithoutSig(credentialList); + if (StringUtils.isEmpty(rawData)) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + ResponseData> claimResp = TimestampUtils + .createWeSignTimestamp(rawData); + if (claimResp.getResult() == null) { + return new ResponseData<>(null, claimResp.getErrorCode(), claimResp.getErrorMessage()); + } + HashMap claim = claimResp.getResult(); + List trimmedCredentialMapList = trimCredentialList(credentialList); + claim.put("credentialList", trimmedCredentialMapList); + credential.setClaim(claim); + + // For embedded signature, salt here is totally meaningless - hence we left it blank + Map saltMap = DataToolUtils.clone(claim); + CredentialPojoUtils.clearMap(saltMap); + //String signature = DataToolUtils.secp256k1Sign(rawData, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(rawData, privateKey) + ); + + credential.putProofValue(ParamKeyConstant.PROOF_CREATED, credential.getIssuanceDate()); + + String creator = weIdAuthentication.getWeId(); + credential.putProofValue(ParamKeyConstant.PROOF_CREATOR, creator); + + String proofType = CredentialProofType.ECDSA.getTypeName(); + credential.putProofValue(ParamKeyConstant.PROOF_TYPE, proofType); + credential.putProofValue(ParamKeyConstant.PROOF_SIGNATURE, signature); + credential.setSalt(saltMap); + + return new ResponseData<>(credential, ErrorCode.SUCCESS); + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#prepareZKPCredential( + * com.webank.weid.protocol.base.CredentialPojo, java.lang.Object) + */ + @Override + public ResponseData prepareZkpCredential( + CredentialPojo preCredential, + String claimJson, + WeIdAuthentication weIdAuthentication) { + + //1. verify pre-credential. + ResponseData verifyResult = this.verify(preCredential.getIssuer(), preCredential); + if (verifyResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error("[prepareZKPCredential] pre-credential verified failed."); + return new ResponseData(null, + ErrorCode.getTypeByErrorCode(verifyResult.getErrorCode())); + } + + //2.build credentialInfoMap and make credential. + Integer cptId = (Integer) preCredential.getClaim() + .get(CredentialConstant.CREDENTIAL_META_KEY_CPTID); + UserResult userResult = makeCredential(preCredential, claimJson, cptId, weIdAuthentication); + + //3. generate credential based on CPT 111 and userResult. + return generateCpt111Credential(weIdAuthentication, cptId, userResult); + } + + /** + * generate credential based on cpt 111. + * + * @param weIdAuthentication auth + * @param cptId cpt id + * @param userResult userResult made by user + * @return credential signed by user. + */ + private ResponseData generateCpt111Credential( + WeIdAuthentication weIdAuthentication, + Integer cptId, + UserResult userResult) { + + Cpt111 cpt111 = new Cpt111(); + cpt111.setCptId(String.valueOf(cptId)); + cpt111.setCredentialSignatureRequest(userResult.credentialSignatureRequest); + cpt111.setUserNonce(userResult.userNonce); + CreateCredentialPojoArgs args = new CreateCredentialPojoArgs(); + args.setClaim(cpt111); + args.setWeIdAuthentication(weIdAuthentication); + args.setCptId(CredentialConstant.ZKP_USER_NONCE_CPT); + args.setIssuer(weIdAuthentication.getWeId()); + //args.setId(preCredential.getId()); + args.setIssuanceDate(System.currentTimeMillis()); + args.setExpirationDate(System.currentTimeMillis() + 24 * 60 * 60 * 1000); + return this.createCredential(args); + } + + private ResponseData createZkpCredential( + CredentialPojo credential, + ClaimPolicy claimPolicy, + String userId) { + try { + CredentialPojo credentialClone = DataToolUtils.clone(credential); + ErrorCode checkResp = CredentialPojoUtils.isCredentialPojoValid(credentialClone); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return new ResponseData(null, checkResp); + } + if (credentialClone.getCptId() + .equals(CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT)) { + return new ResponseData<>(null, ErrorCode.CPT_ID_ILLEGAL); + } + if (claimPolicy == null) { + logger.error("[createZkpCredential] claimPolicy is null."); + return new ResponseData(null, + ErrorCode.CREDENTIAL_CLAIM_POLICY_NOT_EXIST); + } + List revealedAttributeList = new ArrayList<>(); + List predicateList = new ArrayList<>(); + + processZkpPolicy(claimPolicy, revealedAttributeList, predicateList); + VerificationRule verificationRule = + VerificationRule.newBuilder() + .addAllRevealedAttribute(revealedAttributeList) + .addAllPredicateAttribute(predicateList) + .build(); + String encodedVerificationRule = Utils.protoToEncodedString(verificationRule); + ResponseData dbResp = + getDataDriver().get( + DataDriverConstant.DOMAIN_USER_CREDENTIAL_SIGNATURE, + credential.getId()); + Integer cptId = credentialClone.getCptId(); + String id = new StringBuffer().append(userId).append("_").append(cptId).toString(); + String newCredentialSignature = dbResp.getResult(); + ResponseData masterKeyResp = + getDataDriver().get( + DataDriverConstant.DOMAIN_USER_MASTER_SECRET, + id); + HashMap userCredentialInfo = DataToolUtils + .deserialize(masterKeyResp.getResult(), HashMap.class); + String masterSecret = userCredentialInfo.get("masterSecret"); + ResponseData credentialTemplateResp = getCptService() + .queryCredentialTemplate(cptId); + CredentialTemplateEntity credentialTemplate = credentialTemplateResp.getResult(); + Map credentialInfoMap = new HashMap<>(); + credentialInfoMap = JsonUtil.credentialToMonolayer(credential); + UserResult userResult = + UserClient.proveCredentialInfo( + encodedVerificationRule, + newCredentialSignature, //from db + credentialInfoMap, //from credential + credentialTemplate, //from blockchain and cpt + masterSecret); //from db + + String verificationRequest = userResult.verificationRequest; + + porcessZkpDisclosedValue(credentialClone, claimPolicy); + //CredentialPojo zkpCredential = new CredentialPojo(); + credentialClone.setProof(null); + credentialClone + .putProofValue(ParamKeyConstant.PROOF_VERIFICATIONREQUEST, verificationRequest); + credentialClone.putProofValue(ParamKeyConstant.PROOF_ENCODEDVERIFICATIONRULE, + encodedVerificationRule); + List zkpTyps = new ArrayList<>(); + zkpTyps.add(CredentialConstant.DEFAULT_CREDENTIAL_TYPE); + zkpTyps.add(CredentialType.ZKP.getName()); + credentialClone.setType(zkpTyps); + return new ResponseData(credentialClone, ErrorCode.SUCCESS); + } catch (DataTypeCastException e) { + logger.error("Generate SelectiveCredential failed, " + + "credential disclosure data type illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL); + } catch (WeIdBaseException e) { + logger.error("Generate SelectiveCredential failed, " + + "policy disclosurevalue illegal. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL); + } catch (Exception e) { + logger.error("Generate SelectiveCredential failed due to system error. ", e); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); + } + + } + + private void porcessZkpDisclosedValue(CredentialPojo credential, ClaimPolicy claimPolicy) { + + String disclosure = claimPolicy.getFieldsToBeDisclosed(); + Map saltMap = credential.getSalt(); + Map claim = credential.getClaim(); + + Map disclosureMap = DataToolUtils + .deserialize(disclosure, HashMap.class); + + Map claimDisclosureMap = (Map) disclosureMap.get("claim"); + if (claimDisclosureMap == null || !(claimDisclosureMap instanceof Map)) { + return; + } + // 补 policy + addKeyToPolicy(claimDisclosureMap, claim); + // 加盐处理 + addSelectSalt(claimDisclosureMap, saltMap, claim, true); + + disclosureMap.remove("claim"); + processMetaDisclosedValue(credential, disclosureMap); + + } + + private void processMetaDisclosedValue(CredentialPojo credential, + Map disclosureMap) { + + for (Map.Entry entry : disclosureMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + String salt = DataToolUtils.getRandomSalt(); + if ((value instanceof Map) || !StringUtils.equals(String.valueOf(value), DISCLOSED)) { + switch (key) { + case CredentialConstant.ID: + credential + .setId(CredentialPojoUtils.getFieldSaltHash(credential.getId(), salt)); + break; + case CredentialConstant.CREDENTIAL_META_KEY_ISSUANCEDATE: + credential.setIssuanceDate(0L); + break; + case CredentialConstant.CREDENTIAL_META_KEY_EXPIRATIONDATE: + credential.setExpirationDate(0L); + break; + case CredentialConstant.CREDENTIAL_META_KEY_CPTID: + credential.setCptId(0); + break; + case CredentialConstant.CREDENTIAL_META_KEY_ISSUER: + credential.setIssuer( + CredentialPojoUtils.getFieldSaltHash(credential.getIssuer(), salt)); + break; + case CredentialConstant.CREDENTIAL_META_KEY_CONTEXT: + credential.setIssuer( + CredentialPojoUtils.getFieldSaltHash(credential.getContext(), salt)); + break; + default: + break; + } + } + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.CredentialPojoService#createDataAuthToken() + */ + @Override + public ResponseData createDataAuthToken( + Cpt101 authInfo, + WeIdAuthentication weIdAuthentication) { + ErrorCode innerErrorCode = + CredentialPojoUtils.isWeIdAuthenticationValid(weIdAuthentication); + if (innerErrorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(null, innerErrorCode); + } + + CreateCredentialPojoArgs args = new CreateCredentialPojoArgs(); + args.setClaim(authInfo); + args.setWeIdAuthentication(weIdAuthentication); + args.setId(UUID.randomUUID().toString()); + args.setContext(CredentialUtils.getDefaultCredentialContext()); + args.setCptId(CredentialConstant.AUTHORIZATION_CPT); + String privateKey = weIdAuthentication.getWeIdPrivateKey().getPrivateKey(); + String keyWeId = WeIdUtils.convertAddressToWeId(DataToolUtils.addressFromPrivate(new BigInteger(privateKey))); + args.setIssuer(keyWeId); + args.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + args.setExpirationDate(args.getIssuanceDate() + authInfo.getDuration()); + ResponseData resp = this.createCredential(args); + innerErrorCode = verifyAuthClaim(resp.getResult()); + if (innerErrorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(null, innerErrorCode); + } + return resp; + } + + @Override + public ResponseData> checkCredentialWithCpt( + CredentialPojo credential, + Cpt cpt + ) { + try { + if (credential == null || credential.getSalt() == null + || credential.getClaim() == null || credential.getType() == null) { + String errorMsg = ErrorCode.ILLEGAL_INPUT.getCodeDesc() + ": credential"; + logger.error("[checkCredentialWithCpt] {}.", errorMsg); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT.getCode(), errorMsg); + } + if (cpt == null || cpt.getCptJsonSchema() == null) { + String errorMsg = ErrorCode.ILLEGAL_INPUT.getCodeDesc() + ": cpt"; + logger.error("[checkCredentialWithCpt] {}.", errorMsg); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT.getCode(), errorMsg); + } + if (credential.getCptId().intValue() != cpt.getCptId().intValue()) { + logger.error("[checkCredentialWithCpt] the cptId does not match."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_CPTID_NOTMATCH); + } + // zkp不支持检查 + if (credential.getCredentialType() == CredentialType.ZKP) { + logger.error("[checkCredentialWithCpt] ZKP Credential DO NOT support."); + return new ResponseData<>(null, ErrorCode.THIS_IS_UNSUPPORTED); + } else if (credential.getCredentialType() == CredentialType.ORIGINAL) { + // 如果不是lite1类型的,则判断是否为选择性披露类型 + boolean isSelectivelyDisclosed = CredentialPojoUtils.isSelectivelyDisclosed( + credential.getSalt()); + // 如果是选择性披露 则特殊处理 + if (isSelectivelyDisclosed) { + // 做特殊处理逻辑: remove不披露的字段 并判断是否为必选字段,如果是必选字段 并且为不披露则检查失败 + credential = DataToolUtils.clone(credential); + removeDisclosedFiledMap( + credential.getClaim(), + credential.getSalt(), + cpt.getCptJsonSchema() + ); + } + } + + String cptJsonSchema = DataToolUtils.serialize(cpt.getCptJsonSchema()); + // 验证cpt自身的合法性 + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { + logger.error("[checkCredentialWithCpt] the cpt invalid."); + return new ResponseData<>(null, ErrorCode.CPT_JSON_SCHEMA_INVALID); + } + String claimStr = DataToolUtils.serialize(credential.getClaim()); + // 验证cpt与credential的匹配性 + Set checkRes = DataToolUtils.checkJsonVersusSchema( + claimStr, cptJsonSchema); + if (checkRes.size() != 0) { + logger.error( + "[checkCredentialWithCpt] check fail, ProcessingReport = {}.", checkRes); + ResponseData> result = new ResponseData<>( + checkRes, + ErrorCode.CREDENTIAL_DOES_NOT_MATCHE_THE_CPT + ); + return result; + } + return new ResponseData<>(checkRes, ErrorCode.SUCCESS); + } catch (WeIdBaseException e) { + logger.error("[checkCredentialWithCpt] check has base exception.", e); + return new ResponseData<>(null, e.getErrorCode().getCode(), e.getMessage()); + } catch (Exception e) { + logger.error("[checkCredentialWithCpt] check has unknown exception.", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + // 移除不披露的字段 + private void removeDisclosedFiledMap( + Map claim, + Map salt, + Map properties + ) { + ArrayList requireds = (ArrayList)properties.get("required"); + Map nextProperties = (Map)properties.get("properties"); + // 遍历claim + for (Map.Entry entry : salt.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof Map) { + // 说明下一层为map + removeDisclosedFiledMap( + (Map) claim.get(key), + (Map) value, + (Map) nextProperties.get(key) + ); + } else if (value instanceof List) { + // 说明下一层是List + removeDisclosedFiledList( + (ArrayList) claim.get(key), + (ArrayList) value, + (Map) nextProperties.get(key)); + } else { + // 说明当前层为需要处理的层 + // 如果当前为不披露的key + // 1. 如果必须的key则报错 + // 2. 否则移除此key + if ("0".equals(value.toString())) { + // 说明是选择性披露 + if (requireds != null && requireds.contains(key)) { + throw new WeIdBaseException(key + " is required and disclosed."); + } else { + claim.remove(key); + } + } + } + } + } + + private void removeDisclosedFiledList( + ArrayList claims, + ArrayList salts, + Map properties + ) { + for (int i = 0; i < claims.size(); i++) { + Object claim = claims.get(i); + if (claim instanceof Map) { + removeDisclosedFiledMap( + (Map) claim, + (Map) salts.get(i), + (Map) properties.get("items") + ); + } else { + removeDisclosedFiledList( + (ArrayList) claim, + (ArrayList) salts.get(i), + (Map) properties.get("items") + ); + } + } + } +} diff --git a/src/main/java/com/webank/weid/service/impl/CredentialServiceImpl.java b/src/main/java/com/webank/weid/service/impl/CredentialServiceImpl.java index 350b70f8..d7ee9a0c 100644 --- a/src/main/java/com/webank/weid/service/impl/CredentialServiceImpl.java +++ b/src/main/java/com/webank/weid/service/impl/CredentialServiceImpl.java @@ -1,70 +1,41 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ package com.webank.weid.service.impl; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.crypto.Sign; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.protocol.base.AuthenticationProperty; -import com.webank.weid.protocol.base.Cpt; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.PublicKeyProperty; -import com.webank.weid.protocol.base.WeIdDocument; +import com.networknt.schema.ValidationMessage; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.CredentialFieldDisclosureValue; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.*; import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.CptService; -import com.webank.weid.rpc.CredentialService; -import com.webank.weid.rpc.WeIdService; -import com.webank.weid.service.BaseService; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.rpc.CptService; +import com.webank.weid.service.rpc.CredentialService; +import com.webank.weid.service.rpc.WeIdService; import com.webank.weid.util.CredentialUtils; -import com.webank.weid.util.JsonSchemaValidatorUtils; -import com.webank.weid.util.SignatureUtils; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.*; /** * Service implementations for operations on Credential. * - * @author chaoxinhu 2018.10 + * @author chaoxinhu 2019.1 */ -@Component -public class CredentialServiceImpl extends BaseService implements CredentialService { +public class CredentialServiceImpl implements CredentialService { private static final Logger logger = LoggerFactory.getLogger(CredentialServiceImpl.class); - @Autowired - private CptService cptService; + private CptService cptService = new CptServiceImpl(); - @Autowired - private WeIdService weIdService; + private WeIdService weIdService = new WeIdServiceImpl(); /** @@ -74,15 +45,14 @@ public class CredentialServiceImpl extends BaseService implements CredentialServ * @return the Credential response data */ @Override - public ResponseData createCredential(CreateCredentialArgs args) { - ResponseData responseData = new ResponseData(); + public ResponseData createCredential(CreateCredentialArgs args) { + CredentialWrapper credentialWrapper = new CredentialWrapper(); try { - ResponseData innerResponse = checkCreateCredentialArgsValidity(args, true); - if (!innerResponse.getResult()) { + ErrorCode innerResponse = checkCreateCredentialArgsValidity(args, true); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { logger.error("Generate Credential input format error!"); - return new ResponseData( - null, innerResponse.getErrorCode(), innerResponse.getErrorMessage()); + return new ResponseData<>(null, innerResponse); } Credential result = new Credential(); @@ -90,188 +60,327 @@ public ResponseData createCredential(CreateCredentialArgs args) { result.setContext(context); result.setId(UUID.randomUUID().toString()); result.setCptId(args.getCptId()); + result.setIssuer(args.getIssuer()); - result.setIssuranceDate(new Long(System.currentTimeMillis())); - result.setExpirationDate(new Long(args.getExpirationDate())); + Long issuanceDate = args.getIssuanceDate(); + if (issuanceDate == null) { + result.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + } else { + Long newIssuanceDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getIssuanceDate()); + if (newIssuanceDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL); + } else { + result.setIssuanceDate(newIssuanceDate); + } + } + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp(args.getExpirationDate()); + if (newExpirationDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + } else { + result.setExpirationDate(newExpirationDate); + } result.setClaim(args.getClaim()); - String rawData = CredentialUtils.getCredentialFields(result); - String privateKey = args.getWeIdPrivateKey().getPrivateKey(); - Sign.SignatureData sigData = SignatureUtils.signMessage(rawData, privateKey); - result.setSignature( - new String( - SignatureUtils - .base64Encode(SignatureUtils.simpleSignatureSerialization(sigData)))); - responseData.setResult(result); + Map disclosureMap = new HashMap<>(args.getClaim()); + for (Map.Entry entry : disclosureMap.entrySet()) { + disclosureMap.put( + entry.getKey(), + CredentialFieldDisclosureValue.DISCLOSED.getStatus() + ); + } + credentialWrapper.setDisclosure(disclosureMap); + + // Construct Credential Proof + //替换国密 + Map credentialProof = CredentialUtils.buildCredentialProof( + result, + args.getWeIdPrivateKey().getPrivateKey(), + disclosureMap); + result.setProof(credentialProof); + + credentialWrapper.setCredential(result); + ResponseData responseData = new ResponseData<>( + credentialWrapper, + ErrorCode.SUCCESS + ); + + return responseData; } catch (Exception e) { logger.error("Generate Credential failed due to system error. ", e); - return new ResponseData(null, ErrorCode.CREDENTIAL_ERROR); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_ERROR); } - return responseData; + } + + private boolean isMultiSignedCredential(Credential credential) { + if (credential == null) { + return false; + } + return (credential.getCptId() == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + .intValue()); + } + + /** + * Add an extra signer and signature to a Credential. Multiple signatures will be appended in an + * embedded manner. + * + * @param credentialList original credential + * @param weIdPrivateKey the passed-in privateKey and WeID bundle to sign + * @return the modified CredentialWrapper + */ + @Override + public ResponseData addSignature( + List credentialList, + WeIdPrivateKey weIdPrivateKey) { + if (credentialList == null || credentialList.size() == 0 || !WeIdUtils + .isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + Credential result = new Credential(); + result.setCptId(CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT); + result.setIssuanceDate(DateUtils.getNoMillisecondTimeStamp()); + result.setId(UUID.randomUUID().toString()); + result.setContext(CredentialUtils.getDefaultCredentialContext()); + Long expirationDate = 0L; + for (Credential arg : credentialList) { + if (arg.getExpirationDate() > expirationDate) { + expirationDate = arg.getExpirationDate(); + } + } + Long newExpirationDate = + DateUtils.convertToNoMillisecondTimeStamp(expirationDate); + if (newExpirationDate == null) { + logger.error("Create Credential Args illegal."); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + } else { + result.setExpirationDate(newExpirationDate); + } + String privateKey = weIdPrivateKey.getPrivateKey(); + /*ECKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate(new BigInteger(privateKey)); + String keyWeId = WeIdUtils + .convertAddressToWeId(new Address(Keys.getAddress(keyPair)).toString());*/ + //CryptoKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate(new BigInteger(privateKey)); + String keyWeId = WeIdUtils.convertAddressToWeId(DataToolUtils.addressFromPrivate(new BigInteger(privateKey))); + if (!weIdService.isWeIdExist(keyWeId).getResult()) { + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + result.setIssuer(keyWeId); + + // Check and remove duplicates in the credentialList + List trimmedCredentialList = new ArrayList<>(); + for (Credential arg : credentialList) { + boolean found = false; + for (Credential credAlive : trimmedCredentialList) { + if (CredentialUtils.isEqual(arg, credAlive)) { + found = true; + break; + } + } + if (!found) { + trimmedCredentialList.add(arg); + } + } + + Map claim = new HashMap<>(); + claim.put("credentialList", trimmedCredentialList); + result.setClaim(claim); + //替换国密 + Map credentialProof = CredentialUtils + .buildCredentialProof(result, privateKey, null); + result.setProof(credentialProof); + return new ResponseData<>(result, ErrorCode.SUCCESS); } /** * Verify the validity of a credential without public key provided. * - * @param args the args + * @param credentialWrapper the credential wrapper. * @return the Boolean response data */ @Override - public ResponseData verifyCredential(Credential args) { - return verifyCredentialContent(args, null); + public ResponseData verify(CredentialWrapper credentialWrapper) { + return verifyCredentialContent(credentialWrapper, null); + } + + /** + * Verify Credential validity. + */ + @Override + public ResponseData verify(Credential credential) { + Map disclosureMap = new HashMap<>(credential.getClaim()); + for (Map.Entry entry : disclosureMap.entrySet()) { + disclosureMap.put(entry.getKey(), CredentialFieldDisclosureValue.DISCLOSED.getStatus()); + } + CredentialWrapper credentialWrapper = new CredentialWrapper(); + credentialWrapper.setCredential(credential); + credentialWrapper.setDisclosure(disclosureMap); + return verifyCredentialContent(credentialWrapper, null); } /** * Verify the validity of a credential with public key provided. * - * @param args the args + * @param credentialWrapper the args + * @param weIdPublicKey the specific public key to verify the credential. * @return the Boolean response data */ @Override - public ResponseData verifyCredentialWithSpecifiedPubKey(VerifyCredentialArgs args) { - if (args == null) { + public ResponseData verifyCredentialWithSpecifiedPubKey( + CredentialWrapper credentialWrapper, + WeIdPublicKey weIdPublicKey) { + if (credentialWrapper == null) { return new ResponseData(false, ErrorCode.ILLEGAL_INPUT); } - if (args.getWeIdPublicKey() == null) { + if (weIdPublicKey == null) { return new ResponseData(false, ErrorCode.CREDENTIAL_ISSUER_MISMATCH); } - return verifyCredentialContent(args.getCredential(), - args.getWeIdPublicKey().getPublicKey()); + return verifyCredentialContent(credentialWrapper, weIdPublicKey.getPublicKey()); } - private ResponseData verifyCredentialContent(Credential credential, String publicKey) { - ResponseData responseData = new ResponseData(); - - try { - ResponseData innerResponse = checkCredentialArgsValidity(credential); - if (!innerResponse.getResult()) { - logger.error("Credential input format error!"); - return new ResponseData<>( - false, innerResponse.getErrorCode(), innerResponse.getErrorMessage()); - } - - responseData = verifyIssuerExistence(credential.getIssuer()); - if (!responseData.getResult()) { - return responseData; - } - responseData = verifyCptFormat(credential); - if (!responseData.getResult()) { - return responseData; - } - responseData = verifyNotExpired(credential); - if (!responseData.getResult()) { - return responseData; - } - responseData = verifySignature(credential, publicKey); - return responseData; - } catch (Exception e) { - logger.error("Verify Credential failed due to generic error: ", e); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); + /** + * The only standardized inf to create a full Credential Hash for a given Credential. + * + * @param args the args + * @return the Boolean response data + */ + @Override + public ResponseData getCredentialHash(Credential args) { + ErrorCode innerResponse = CredentialUtils.isCredentialValid(args); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { + return new ResponseData<>(StringUtils.EMPTY, innerResponse); } + return new ResponseData<>(CredentialUtils.getCredentialHash(args), ErrorCode.SUCCESS); } - private ResponseData checkCreateCredentialArgsValidity( - CreateCredentialArgs args, boolean privateKeyRequired) { - ResponseData responseData = new ResponseData(); - if (args == null) { - logger.error("Credential argument null input error."); - return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + /** + * Get the full hash value of a Credential with its selectively-disclosure map. All fields in + * the Credential will be included. This method should be called when creating and verifying the + * Credential Evidence and the result is selectively-disclosure irrelevant. + * + * @param credentialWrapper the args + * @return the Credential Hash value in byte array, fixed to be 32 Bytes length + */ + @Override + public ResponseData getCredentialHash(CredentialWrapper credentialWrapper) { + if (credentialWrapper == null) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + if (credentialWrapper.getDisclosure() == null + || credentialWrapper.getDisclosure().size() == 0) { + return getCredentialHash(credentialWrapper.getCredential()); } + Credential credential = credentialWrapper.getCredential(); + ErrorCode innerResponse = CredentialUtils.isCredentialValid(credential); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { + return new ResponseData<>(StringUtils.EMPTY, innerResponse); + } + return new ResponseData<>(CredentialUtils.getCredentialWrapperHash(credentialWrapper), + ErrorCode.SUCCESS); + } - try { - Integer cptId = args.getCptId(); - if (cptId == null) { - logger.error(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CPT_NOT_EXISTS); + private ResponseData verifyCredentialContent(CredentialWrapper credentialWrapper, + String publicKey) { + Credential credential = credentialWrapper.getCredential(); + ErrorCode innerResponse = CredentialUtils.isCredentialValid(credential); + if (ErrorCode.SUCCESS.getCode() != innerResponse.getCode()) { + logger.error("Credential input format error!"); + return new ResponseData<>(false, innerResponse); + } + if (credential.getCptId() == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT + .intValue()) { + return new ResponseData<>(false, ErrorCode.CPT_ID_ILLEGAL); + } + if (credential.getCptId() == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + .intValue()) { + // This is a multi-signed Credential, and its disclosure is against its leaf + Map disclosure = credentialWrapper.getDisclosure(); + // We firstly verify itself + credentialWrapper.setDisclosure(null); + ResponseData innerResp = verifySingleSignedCredential(credentialWrapper, + publicKey); + if (!innerResp.getResult()) { + return new ResponseData<>(false, innerResp.getErrorCode(), + innerResp.getErrorMessage()); } - - String credentialIssuer = args.getIssuer(); - if (!WeIdUtils.isWeIdValid(credentialIssuer)) { - logger.error(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ISSUER_INVALID); + // Then, we verify its list members one-by-one + credentialWrapper.setDisclosure(disclosure); + List innerCredentialList; + try { + if (credentialWrapper.getCredential().getClaim() + .get("credentialList") instanceof String) { + // For selectively-disclosed credential, just skip - external check is enough + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + innerCredentialList = (ArrayList) credentialWrapper.getCredential().getClaim() + .get("credentialList"); + } + } catch (Exception e) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL); } - - Long expirationDate = args.getExpirationDate(); - if (expirationDate == null - || expirationDate.longValue() < 0 - || expirationDate.longValue() == 0) { - logger.error(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL); + for (Credential innerCredential : innerCredentialList) { + credentialWrapper.setCredential(innerCredential); + // Make sure that this disclosure is a meaningful one + if (disclosure != null && disclosure.size() <= 1 + && disclosure.size() != innerCredential.getClaim().size() + && disclosure.containsKey("credentialList")) { + credentialWrapper.setDisclosure(null); + } + if (disclosure == null) { + credentialWrapper.setDisclosure(null); + } + innerResp = verifyCredentialContent(credentialWrapper, publicKey); + if (!innerResp.getResult()) { + return new ResponseData<>(false, innerResp.getErrorCode(), + innerResp.getErrorMessage()); + } } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + return verifySingleSignedCredential(credentialWrapper, publicKey); + } - String claim = args.getClaim(); - if (StringUtils.isEmpty(claim)) { - logger.error(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS); - } + private ResponseData verifySingleSignedCredential(CredentialWrapper credentialWrapper, + String publicKey) { + Credential credential = credentialWrapper.getCredential(); + ResponseData responseData = verifyIssuerExistence(credential.getIssuer()); + if (!responseData.getResult()) { + return responseData; + } - if (privateKeyRequired - && StringUtils.isEmpty(args.getWeIdPrivateKey().getPrivateKey())) { - logger.error(ErrorCode.CREDENTIAL_PRIVATE_KEY_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_PRIVATE_KEY_NOT_EXISTS); - } + ErrorCode errorCode = verifyCptFormat( + credential.getCptId(), + credential.getClaim() + ); + if (ErrorCode.SUCCESS.getCode() != errorCode.getCode()) { + return new ResponseData<>(false, errorCode); + } - responseData.setResult(true); + responseData = verifyNotExpired(credential); + if (!responseData.getResult()) { return responseData; - } catch (Exception e) { - logger.error("Check create Credential args failed due to generic error: ", e); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); } + responseData = verifySignature(credentialWrapper, publicKey); + return responseData; } - private ResponseData checkCredentialArgsValidity(Credential args) { - ResponseData responseData = new ResponseData(); - if (args == null) { - logger.error("Credential argument null input error."); - return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + private ErrorCode checkCreateCredentialArgsValidity( + CreateCredentialArgs args, boolean privateKeyRequired) { + ErrorCode innerResponseData = CredentialUtils.isCreateCredentialArgsValid(args); + if (ErrorCode.SUCCESS.getCode() != innerResponseData.getCode()) { + logger.error("Create Credential Args illegal: {}", innerResponseData.getCodeDesc()); + return innerResponseData; } - - try { - CreateCredentialArgs generateCredentialArgs = CredentialUtils - .extractCredentialMetadata(args); - // Do not need to check privateKey field since it won't be set in this case. - ResponseData innerResponseData = - checkCreateCredentialArgsValidity(generateCredentialArgs, false); - if (!innerResponseData.getResult()) { - return new ResponseData<>( - false, innerResponseData.getErrorCode(), innerResponseData.getErrorMessage()); - } - // Check new fields: id, context, signature, and issurancedate; - String credentialId = args.getId(); - if (StringUtils.isEmpty(credentialId)) { - logger.error(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ID_NOT_EXISTS); - } - - String context = args.getContext(); - if (StringUtils.isEmpty(context)) { - logger.error(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS); - } - - Long issuranceDate = args.getIssuranceDate(); - if (issuranceDate == null) { - logger.error(ErrorCode.CREDENTIAL_CREATE_DATE_ILLEGAL.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CREATE_DATE_ILLEGAL); - } - if (issuranceDate.longValue() > args.getExpirationDate().longValue()) { - logger.error(ErrorCode.CREDENTIAL_EXPIRED.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_EXPIRED); - } - - String signature = args.getSignature(); - if (StringUtils.isEmpty(signature) || !SignatureUtils.isValidBase64String(signature)) { - logger.error(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_SIGNATURE_BROKEN); - } - - responseData.setResult(true); - return responseData; - } catch (Exception e) { - logger.error("Check create Credential args failed due to generic error: ", e); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); + if (privateKeyRequired + && StringUtils.isEmpty(args.getWeIdPrivateKey().getPrivateKey())) { + logger.error(ErrorCode.CREDENTIAL_PRIVATE_KEY_NOT_EXISTS.getCodeDesc()); + return ErrorCode.CREDENTIAL_PRIVATE_KEY_NOT_EXISTS; } + return ErrorCode.SUCCESS; } + private ResponseData verifyIssuerExistence(String issuerWeId) { ResponseData responseData = weIdService.isWeIdExist(issuerWeId); if (responseData == null || !responseData.getResult()) { @@ -280,115 +389,191 @@ private ResponseData verifyIssuerExistence(String issuerWeId) { return responseData; } - private ResponseData verifyCptFormat(Credential credential) { - ResponseData responseData = new ResponseData(); - String claim = credential.getClaim(); - Integer cptId = credential.getCptId(); - Cpt cpt = cptService.queryCpt(cptId).getResult(); - if (cpt == null) { - logger.error(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CPT_NOT_EXISTS); + private ErrorCode verifyCptFormat(Integer cptId, Map claim) { + if (cptId == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT.intValue()) { + if (!claim.containsKey("credentialList")) { + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; + } else { + return ErrorCode.SUCCESS; + } } - String cptJsonSchema = cpt.getCptJsonSchema(); try { - if (!JsonSchemaValidatorUtils.isCptJsonSchemaValid(cptJsonSchema)) { + //String claimStr = JsonUtil.objToJsonStr(claim); + String claimStr = DataToolUtils.serialize(claim); + Cpt cpt = cptService.queryCpt(cptId).getResult(); + if (cpt == null) { + logger.error(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCodeDesc()); + return ErrorCode.CREDENTIAL_CPT_NOT_EXISTS; + } + //String cptJsonSchema = JsonUtil.objToJsonStr(cpt.getCptJsonSchema()); + String cptJsonSchema = DataToolUtils.serialize(cpt.getCptJsonSchema()); + + if (!DataToolUtils.isCptJsonSchemaValid(cptJsonSchema)) { logger.error(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CPT_JSON_SCHEMA_INVALID); + return ErrorCode.CPT_JSON_SCHEMA_INVALID; } - if (!JsonSchemaValidatorUtils.validateJsonVersusSchema(claim, cptJsonSchema)) { + Set checkRes = DataToolUtils.checkJsonVersusSchema( + claimStr, cptJsonSchema); + if (checkRes.size() != 0) { logger.error(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCodeDesc()); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL); + return ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL; } - responseData.setResult(true); - return responseData; + return ErrorCode.SUCCESS; } catch (Exception e) { logger.error( - "Generic error occurred during verify cpt format when verifyCredential: " + e); - return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); + "Generic error occurred during verify cpt format when verifyCredential: " + e); + return ErrorCode.CREDENTIAL_ERROR; } } private ResponseData verifyNotExpired(Credential credential) { - ResponseData responseData = new ResponseData(); - Date expireDate = new Date(credential.getExpirationDate().longValue()); - Date currentDate = new Date(); - boolean result = currentDate.before(expireDate); - responseData.setResult(result); - if (!result) { - responseData.setErrorCode(ErrorCode.CREDENTIAL_EXPIRED.getCode()); - responseData.setErrorMessage(ErrorCode.CREDENTIAL_EXPIRED.getCodeDesc()); + try { + boolean result = DateUtils.isAfterCurrentTime(credential.getExpirationDate()); + ResponseData responseData = new ResponseData<>(result, ErrorCode.SUCCESS); + if (!result) { + responseData.setErrorCode(ErrorCode.CREDENTIAL_EXPIRED); + } + return responseData; + } catch (Exception e) { + logger.error( + "Generic error occurred during verify expiration when verifyCredential: " + e); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); } - return responseData; } - private ResponseData verifySignature(Credential credential, String publicKey) { - - ResponseData responseData = new ResponseData(); + private ResponseData verifySignature( + CredentialWrapper credentialWrapper, + String publicKey) { + try { - String hashedRawData = CredentialUtils.getCredentialFields(credential); - Sign.SignatureData signatureData = - SignatureUtils.simpleSignatureDeserialization( - SignatureUtils.base64Decode(credential.getSignature().getBytes())); + Credential credential = credentialWrapper.getCredential(); + Map disclosureMap = credentialWrapper.getDisclosure(); + String rawData = CredentialUtils + .getCredentialThumbprintWithoutSig(credential, disclosureMap); + /*Sign.SignatureData signatureData = + DataToolUtils.simpleSignatureDeserialization( + DataToolUtils.base64Decode( + credential.getSignature().getBytes(StandardCharsets.UTF_8) + ) + );*/ if (StringUtils.isEmpty(publicKey)) { // Fetch public key from chain String credentialIssuer = credential.getIssuer(); ResponseData innerResponseData = - weIdService.getWeIdDocument(credentialIssuer); + weIdService.getWeIdDocument(credentialIssuer); if (innerResponseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { logger.error( - "Error occurred when fetching WeIdentity DID document for: " - + credentialIssuer - + ", msg: " - + innerResponseData.getErrorMessage()); + "Error occurred when fetching WeIdentity DID document for: {}, msg: {}", + credentialIssuer, innerResponseData.getErrorMessage()); return new ResponseData<>(false, ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL); } else { - // Traverse public key list indexed Authentication key list WeIdDocument weIdDocument = innerResponseData.getResult(); - - List publicKeysListToVerify = new ArrayList(); - for (AuthenticationProperty authenticationProperty : weIdDocument - .getAuthentication()) { - String index = authenticationProperty.getPublicKey(); - for (PublicKeyProperty publicKeyProperty : weIdDocument.getPublicKey()) { - if (publicKeyProperty.getId().equalsIgnoreCase(index)) { - publicKeysListToVerify.add(publicKeyProperty.getPublicKey()); - } - } - } - boolean result = false; - for (String publicKeyItem : publicKeysListToVerify) { - if (!StringUtils.isEmpty(publicKeyItem)) { - result = - result - || SignatureUtils.verifySignature( - hashedRawData, signatureData, new BigInteger(publicKeyItem)); - } - } - responseData.setResult(result); - if (!result) { - responseData.setErrorCode(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode()); - responseData - .setErrorMessage(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCodeDesc()); + //替换国密 + ErrorCode errorCode = DataToolUtils + .verifySignatureFromWeId(rawData, credential.getSignature(), + weIdDocument, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, errorCode); } - return responseData; + return new ResponseData<>(true, ErrorCode.SUCCESS); } } else { boolean result = - SignatureUtils - .verifySignature(hashedRawData, signatureData, new BigInteger(publicKey)); - responseData.setResult(result); + DataToolUtils.verifySignature(rawData, + credential.getSignature(), new BigInteger(publicKey)); if (!result) { - responseData.setErrorCode(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode()); - responseData - .setErrorMessage(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCodeDesc()); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_VERIFY_FAIL); } - return responseData; + return new ResponseData<>(true, ErrorCode.SUCCESS); } + } catch (WeIdBaseException e) { + logger.error( + "Generic signatureException occurred during verify signature ", e); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_SIGNATURE_BROKEN); } catch (Exception e) { logger.error( - "Generic error occurred during verify signature when verifyCredential: " + e); + "Generic exception occurred during verify signature when verifyCredential: ", e); return new ResponseData<>(false, ErrorCode.CREDENTIAL_ERROR); } } + + /** + * Generate a credential with selected data. + * + * @param credential the credential + * @param disclosure the keys which select to disclosure + * @return credential + */ + @Override + public ResponseData createSelectiveCredential( + Credential credential, + String disclosure) { + + //setp 1: check if the input args is illegal. + CredentialWrapper credentialResult = new CredentialWrapper(); + ErrorCode checkResp = CredentialUtils.isCredentialValid(credential); + if (ErrorCode.SUCCESS.getCode() != checkResp.getCode()) { + return new ResponseData<>(credentialResult, checkResp); + } + if (isMultiSignedCredential(credential)) { + return new ResponseData<>(credentialResult, ErrorCode.CPT_ID_ILLEGAL); + } + + //step 2: convet values of claim to hash by disclosure status + Map claim = credential.getClaim(); + Map hashMap = new HashMap(claim); + + for (Map.Entry entry : claim.entrySet()) { + claim.put(entry.getKey(), CredentialUtils.getFieldHash(entry.getValue())); + } + Map disclosureMap = DataToolUtils.deserialize(disclosure, HashMap.class); + + for (Map.Entry entry : disclosureMap.entrySet()) { + if (CredentialFieldDisclosureValue.DISCLOSED.getStatus() + .equals(entry.getValue())) { + claim.put(entry.getKey(), hashMap.get(entry.getKey())); + } + } + + // step 3: build response of selective credential to caller. + credentialResult.setCredential(credential); + credentialResult.setDisclosure(disclosureMap); + + return new ResponseData<>(credentialResult, ErrorCode.SUCCESS); + } + + /** + * Get the Json String of a Credential. All fields in the Credential will be included. This also + * supports the selectively disclosed Credential. + * + * @param credential the credential wrapper + * @return the Credential Json value in String + */ + @Override + public ResponseData getCredentialJson(Credential credential) { + ErrorCode errorCode = CredentialUtils.isCredentialValid(credential); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>( + StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(errorCode.getCode()) + ); + } + // Convert timestamp into UTC timezone + try { + Map credMap = DataToolUtils.objToMap(credential); + String issuanceDate = DateUtils.convertTimestampToUtc(credential.getIssuanceDate()); + String expirationDate = DateUtils.convertTimestampToUtc(credential.getExpirationDate()); + credMap.put(ParamKeyConstant.ISSUANCE_DATE, issuanceDate); + credMap.put(ParamKeyConstant.EXPIRATION_DATE, expirationDate); + credMap.remove(ParamKeyConstant.CONTEXT); + credMap.put(CredentialConstant.CREDENTIAL_CONTEXT_PORTABLE_JSON_FIELD, + CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT); + String credentialString = DataToolUtils.mapToCompactJson(credMap); + return new ResponseData<>(credentialString, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("Json conversion failed in getCredentialJson: ", e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.CREDENTIAL_ERROR); + } + } } diff --git a/src/main/java/com/webank/weid/service/impl/EvidenceServiceImpl.java b/src/main/java/com/webank/weid/service/impl/EvidenceServiceImpl.java new file mode 100644 index 00000000..17329f9a --- /dev/null +++ b/src/main/java/com/webank/weid/service/impl/EvidenceServiceImpl.java @@ -0,0 +1,929 @@ + + +package com.webank.weid.service.impl; + +import com.google.common.base.Charsets; +import com.google.common.io.Files; + + +import com.webank.weid.service.local.EvidenceServiceLocal; +import com.webank.weid.service.local.WeIdServiceLocal; +import com.webank.weid.service.rpc.EvidenceService; +import com.webank.weid.service.rpc.WeIdService; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ProcessingMode; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.inf.Hashable; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.*; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Service implementations for operations on Evidence. + * + * @author afeexian 2022.10 + */ +public class EvidenceServiceImpl implements EvidenceService { + + private static final Logger logger = LoggerFactory.getLogger(EvidenceServiceImpl.class); + + private WeIdService weIdService = new WeIdServiceImpl(); + + private ProcessingMode processingMode = ProcessingMode.IMMEDIATE; + + //private EvidenceServiceEngine evidenceServiceEngine; + + private static com.webank.weid.blockchain.rpc.EvidenceService evidenceBlockchainService; + + //private String groupId; + + public EvidenceServiceImpl() { + //super(); + //initEvidenceServiceEngine(masterGroupId); + evidenceBlockchainService = getEvidenceService(StringUtils.EMPTY); + } + + private static com.webank.weid.blockchain.rpc.EvidenceService getEvidenceService(String groupId) { + if(evidenceBlockchainService != null) { + return evidenceBlockchainService; + } else { + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("blockchain")) { + if(!groupId.equals(StringUtils.EMPTY)) { + return new com.webank.weid.blockchain.service.impl.EvidenceServiceImpl(groupId); + } else { + return new com.webank.weid.blockchain.service.impl.EvidenceServiceImpl(); + } + } else { + // default database + return new EvidenceServiceLocal(); + } + } + } + + /** + * 传入processingMode来决定上链模式,仅适用于FiscoBcos区块链,用于初始化不同群组的evidence服务. + * + * @param processingMode 上链模式 + * @param groupId 群组编号 + */ + public EvidenceServiceImpl(ProcessingMode processingMode, String groupId) { + //super(groupId); + this.processingMode = processingMode; + //initEvidenceServiceEngine(groupId); + evidenceBlockchainService = getEvidenceService(groupId); + } + + /*private void initEvidenceServiceEngine(String groupId) { + evidenceServiceEngine = EngineFactory.createEvidenceServiceEngine(groupId); + this.groupId = groupId; + }*/ + + @Override + public ResponseData createRawEvidenceWithCustomKey( + String hashValue, + String signature, + String log, + Long timestamp, + String extraKey, + String privateKey + ) { + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.createEvidenceWithCustomKey( + hashValue, + signature, + log, + timestamp, + extraKey, + privateKey + ); + if (hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } + + + @Override + public ResponseData createRawEvidenceWithSpecificSigner( + String hashValue, + String signature, + String log, + Long timestamp, + String extraKey, + String signer, + String privateKey + ) { + List hashValues = new ArrayList<>(); + hashValues.add(hashValue); + List signatures = new ArrayList<>(); + signatures.add(signature); + List logs = new ArrayList<>(); + logs.add(log); + List timestamps = new ArrayList<>(); + timestamps.add(timestamp); + List signers = new ArrayList<>(); + signers.add(signer); + if (StringUtils.isEmpty(extraKey)) { + com.webank.weid.blockchain.protocol.response.ResponseData> hashResp = evidenceBlockchainService.batchCreateEvidence( + hashValues, + signatures, + logs, + timestamps, + signers, + privateKey + ); + if (hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode() && hashResp.getResult().get(0)) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } else { + List extraKeys = new ArrayList<>(); + extraKeys.add(extraKey); + com.webank.weid.blockchain.protocol.response.ResponseData> hashResp = evidenceBlockchainService.batchCreateEvidenceWithCustomKey( + hashValues, + signatures, + logs, + timestamps, + signers, + extraKeys, + privateKey + ); + if (hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode() && hashResp.getResult().get(0)) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } + } + + /** + * Create a new evidence to the blockchain and get the evidence address. + * + * @param object the given Java object + * @param weIdPrivateKey the caller WeID Authentication + * @return Evidence address + */ + @Override + public ResponseData createEvidence(Hashable object, WeIdPrivateKey weIdPrivateKey) { + ResponseData hashResp = getHashValue(object); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(StringUtils.EMPTY, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + return hashToNewEvidence(hashResp.getResult(), weIdPrivateKey.getPrivateKey(), + "empty log"); + } + + /** + * Create a new evidence to blockchain and return the hash value, with appending log. This will + * fail if evidence already exists. + * + * @param object the given Java object + * @param log appendable log entry - can be null or empty + * @param weIdAuthentication weid authentication (only checks private key) + */ + @Override + public ResponseData createEvidenceWithLog( + Hashable object, + String log, + WeIdAuthentication weIdAuthentication + ) { + ResponseData hashResp = getHashValue(object); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(StringUtils.EMPTY, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + if (weIdAuthentication == null + || !WeIdUtils.isPrivateKeyValid(weIdAuthentication.getWeIdPrivateKey())) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + if (!DataToolUtils.isUtf8String(log)) { + logger.error("Evidence argument illegal input: log."); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + if (!isChainStringLengthValid(log)) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ON_CHAIN_STRING_TOO_LONG); + } + return hashToNewEvidence( + hashResp.getResult(), + weIdAuthentication.getWeIdPrivateKey().getPrivateKey(), + log); + } + + /** + * Add log entry for an existing evidence. This log will be recorded on blockchain permanently, + * and finally it will be fetched as a list when trying to get evidence. + * + * @param hashValue hash value + * @param log not null log entry + * @param weIdPrivateKey the signer WeID's private key + */ + @Override + public ResponseData addLogByHash(String hashValue, String log, + WeIdPrivateKey weIdPrivateKey) { + return addByHash( + hashValue, + log, + weIdPrivateKey, + false + ); + } + + /** + * Add signature and log as a new signer to an existing evidence. Log can be empty. + * + * @param hashValue hash value + * @param log log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + @Override + public ResponseData addSignatureAndLogByHash(String hashValue, String log, + WeIdPrivateKey weIdPrivateKey) { + return addByHash( + hashValue, + log, + weIdPrivateKey, + true + ); + } + + private ResponseData addByHash( + String hashValue, + String log, + WeIdPrivateKey weIdPrivateKey, + boolean requireSig + ) { + if (!DataToolUtils.isValidHash(hashValue) || (StringUtils.isEmpty(log) && !requireSig) + || !DataToolUtils.isUtf8String(log)) { + logger.error("Evidence argument illegal input: hash or log."); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if (!isChainStringLengthValid(log)) { + return new ResponseData<>(false, ErrorCode.ON_CHAIN_STRING_TOO_LONG); + } + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + Long timestamp = DateUtils.getNoMillisecondTimeStamp(); + if (requireSig) { + /*String signature = DataToolUtils.secp256k1Sign(hashValue, + new BigInteger(weIdPrivateKey.getPrivateKey()));*/ + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(hashValue, weIdPrivateKey.getPrivateKey()) + ); + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.addLog( + hashValue, + signature, + log, + timestamp, + weIdPrivateKey.getPrivateKey() + ); + if (hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } else { + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.addLog( + hashValue, + StringUtils.EMPTY, + log, + timestamp, + weIdPrivateKey.getPrivateKey() + ); + if (hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } + } + + /** + * Add log entry for an existing evidence, appending on existing log entries. This log will be + * recorded on blockchain permanently, and finally it will be fetched as a list when trying to + * get evidence. Log must not be empty. It will firstly try to fetch the hash value given the + * custom key, and if the hash value does not exist, it will use the supplementing hash value + * (1st parameter) to make up. + * + * @param hashValueSupplement the hash value supplement if the custom key does not exist + * @param customKey custom key + * @param log Not null log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + @Override + public ResponseData addLogByCustomKey( + String hashValueSupplement, + String customKey, + String log, + WeIdPrivateKey weIdPrivateKey) { + return addByCustomKey( + hashValueSupplement, + customKey, + log, + weIdPrivateKey, + false + ); + } + + /** + * Add signature and log as a new signer to an existing evidence. Log can be empty. + * + * @param hashValueSupplement the hash value supplement if the custom key does not exist + * @param customKey custom key + * @param log log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + @Override + public ResponseData addSignatureAndLogByCustomKey( + String hashValueSupplement, + String customKey, + String log, + WeIdPrivateKey weIdPrivateKey + ) { + return addByCustomKey( + hashValueSupplement, + customKey, + log, + weIdPrivateKey, + true + ); + } + + private ResponseData addByCustomKey( + String hashValueSupplement, + String customKey, + String log, + WeIdPrivateKey weIdPrivateKey, + boolean requireSig + ) { + if ((StringUtils.isEmpty(log) && !requireSig) || !DataToolUtils.isUtf8String(log)) { + logger.error("Evidence argument illegal input: log."); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if (StringUtils.isEmpty(customKey) || !DataToolUtils.isUtf8String(customKey)) { + logger.error("Evidence argument illegal input: customKey."); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if (!isChainStringLengthValid(log)) { + return new ResponseData<>(false, ErrorCode.ON_CHAIN_STRING_TOO_LONG); + } + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.getHashByCustomKey(customKey); + String hashValue = hashResp.getResult(); + if (StringUtils.isEmpty(hashValue)) { + logger.error("Failed to find the hash value from custom key: ", customKey); + if (StringUtils.isEmpty(hashValueSupplement)) { + return new ResponseData<>(false, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + hashValue = hashValueSupplement; + } + Long timestamp = DateUtils.getNoMillisecondTimeStamp(); + if (requireSig) { + /*String signature = DataToolUtils.secp256k1Sign(hashValue, + new BigInteger(weIdPrivateKey.getPrivateKey()));*/ + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(hashValue, weIdPrivateKey.getPrivateKey()) + ); + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.addLogByCustomKey( + hashValue, + signature, + log, + timestamp, + customKey, + weIdPrivateKey.getPrivateKey() + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, resp.getErrorCode(), resp.getErrorMessage()); + } + } else { + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.addLogByCustomKey( + hashValue, + StringUtils.EMPTY, + log, + timestamp, + customKey, + weIdPrivateKey.getPrivateKey() + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, resp.getErrorCode(), resp.getErrorMessage()); + } + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.generateHash + * #generateHash(T object) + */ + @Override + public ResponseData generateHash(T object) { + if (object == null) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + //替换国密 + if (object instanceof Hashable) { + ResponseData hashResp = getHashValue((Hashable) object); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(null, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + return new ResponseData<>(new HashString(hashResp.getResult()), ErrorCode.SUCCESS); + } + if (object instanceof File) { + // This will convert all types of file into String stream + String rawData = convertFileToString((File) object); + if (StringUtils.isEmpty(rawData)) { + logger.error("Failed to convert file into String: {}", ((File) object).getName()); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + return new ResponseData<>(new HashString(DataToolUtils.hash(rawData)), + ErrorCode.SUCCESS); + } + if (object instanceof String) { + if (StringUtils.isEmpty((String) object)) { + logger.error("Input String is blank, ignored.."); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + return new ResponseData<>(new HashString(DataToolUtils.hash((String) object)), + ErrorCode.SUCCESS); + } + logger.error("Unsupported input object type: {}", object.getClass().getCanonicalName()); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + + private String convertFileToString(File file) { + try { + return Files.asByteSource(file).asCharSource(Charsets.UTF_8).read(); + } catch (Exception e) { + logger.error("Failed to load file as String.", e); + return StringUtils.EMPTY; + } + } + + /** + * Obtain the hash value of a given object - supports Credential, Wrapper and Pojo, and also + * plain hash value (no extra hashing required). + * + * @param object any object + * @return hash value + */ + private ResponseData getHashValue(Hashable object) { + if (object == null) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + try { + String hashValue = object.getHash(); + if (StringUtils.isEmpty(hashValue)) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + return new ResponseData<>(hashValue, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("Input Object type unsupported: {}", object.getClass().getName(), e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + } + + /** + * Actual method to upload to blockchain, varied in different blockchain versions. + * + * @param hashValue the hash value to be uploaded + * @param privateKey the private key to reload contract and sign txn + * @param extra the extra value (compact json formatted blob) + */ + private ResponseData hashToNewEvidence(String hashValue, String privateKey, + String extra) { + try { + //替换国密 + //String signature = DataToolUtils.secp256k1Sign(hashValue, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(hashValue, privateKey) + ); + Long timestamp = DateUtils.getCurrentTimeStamp(); + if (processingMode == ProcessingMode.PERIODIC_AND_BATCH) { + String[] args = new String[6]; + args[0] = hashValue; + args[1] = signature; + args[2] = extra; + args[3] = String.valueOf(timestamp); + args[4] = privateKey; + args[5] = String.valueOf(evidenceBlockchainService.getGroupId()); + String rawData = new StringBuffer() + .append(hashValue) + .append(signature) + .append(extra) + .append(timestamp) + .append(WeIdUtils.getWeIdFromPrivateKey(privateKey)) + .append(evidenceBlockchainService.getGroupId()).toString(); + //替换国密 + String hash = DataToolUtils.hash(rawData); + String requestId = new BigInteger(hash.substring(2), 16).toString(); + boolean isSuccess = BatchTransactionUtils + .writeTransaction(requestId, "createEvidence", args, StringUtils.EMPTY); + if (isSuccess) { + return new ResponseData<>(hashValue, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(hashValue, ErrorCode.OFFLINE_EVIDENCE_SAVE_FAILED); + } + } + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.createEvidence( + hashValue, + signature, + extra, + timestamp, + privateKey + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(StringUtils.EMPTY, resp.getErrorCode(), resp.getErrorMessage()); + } + } catch (Exception e) { + logger.error("create evidence failed due to system error. ", e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.CREDENTIAL_EVIDENCE_BASE_ERROR); + } + } + + /** + * Get the evidence from blockchain. + * + * @param evidenceKey the evidence hash on chain + * @return The EvidenceInfo + */ + @Override + public ResponseData getEvidence(String evidenceKey) { + if (!DataToolUtils.isValidHash(evidenceKey)) { + logger.error("Evidence argument illegal input: evidence hash. "); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.getInfo(evidenceKey); + if(hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode()){ + EvidenceInfo evidenceInfo = EvidenceInfo.fromBlockChain(hashResp.getResult()); + return new ResponseData<>(evidenceInfo, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } + + /** + * Validate whether a credential created the evidence, and this evidence is signed by this WeID + * - will perform on-Chain key check. + * + * @param credentialPojo the credentialPojo + * @param evidenceInfo the evidence info fetched from chain + * @param weId the WeID + * @return true if yes, false otherwise + */ + @Override + public ResponseData verifySigner( + CredentialPojo credentialPojo, + EvidenceInfo evidenceInfo, + String weId + ) { + return verifySigner(credentialPojo, evidenceInfo, weId, null); + } + + /** + * Validate whether a credential created the evidence, and this evidence is signed by this WeID + * based on the passed-in publicKey. + * + * @param credentialPojo the credentialPojo + * @param evidenceInfo the evidence info fetched from chain + * @param weId the WeID + * @param publicKey the public key + * @return true if yes, false otherwise + */ + @Override + public ResponseData verifySigner( + CredentialPojo credentialPojo, + EvidenceInfo evidenceInfo, + String weId, + String publicKey) { + if (evidenceInfo == null || evidenceInfo.getSigners().isEmpty()) { + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if (!WeIdUtils.isWeIdValid(weId)) { + return new ResponseData<>(false, ErrorCode.WEID_INVALID); + } + if (!evidenceInfo.getSigners().contains(WeIdUtils.convertWeIdToAddress(weId))) { + logger.error("This Evidence does not contain the provided WeID: {}", weId); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + + // 1st: verify hash (accept both thumbprint hash or credential.getHash()) + if (!evidenceInfo.getCredentialHash().equalsIgnoreCase(credentialPojo.getHash())) { + if (CredentialPojoUtils.isLiteCredential(credentialPojo)) { + if (!evidenceInfo.getCredentialHash().equalsIgnoreCase(DataToolUtils.hash( + CredentialPojoUtils.getLiteCredentialThumbprintWithoutSig(credentialPojo)))) { + logger.error("Evidence hash mismatches the lite credential hash or thumbprint"); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_HASH_MISMATCH); + } + } else { + if (CredentialPojoUtils.isEmbeddedCredential(credentialPojo)) { + // Currently unsupported for embedded credential thumbprint hash case + logger.error("Evidence hash mismatches the embedded credential hash"); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_HASH_MISMATCH); + } else { + if (!evidenceInfo.getCredentialHash().equalsIgnoreCase( + DataToolUtils.hash( + CredentialPojoUtils.getCredentialThumbprintWithoutSig(credentialPojo, + credentialPojo.getSalt(), null)))) { + logger.error("Evidence hash mismatches the non-embedded credential hash or" + + "thumbprint"); + return new ResponseData<>(false, + ErrorCode.CREDENTIAL_EVIDENCE_HASH_MISMATCH); + } + } + } + } + + // 2nd: verify signer = issuer + if (!credentialPojo.getIssuer().equalsIgnoreCase(weId)) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_ISSUER_MISMATCH); + } + + // 3rd: verify signature w.r.t. weid (must exist and must be the signer (from pubkey)) + EvidenceSignInfo signInfo = evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(weId)); + String signature = signInfo.getSignature(); + if (!DataToolUtils.isValidBase64String(signature)) { + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_SIGNATURE_BROKEN); + } + /*SignatureData signatureData = + DataToolUtils.simpleSignatureDeserialization( + DataToolUtils.base64Decode(signature.getBytes(StandardCharsets.UTF_8)) + );*/ + + // Firstly, we check the secp256k1 style signature + if (StringUtils.isEmpty(publicKey)) { + ResponseData verifyResp = verifySignatureToSigner( + evidenceInfo.getCredentialHash(), + weId, + signature); + return verifyResp; + } else { + try { + /*boolean result = DataToolUtils + .verifySecp256k1Signature(evidenceInfo.getCredentialHash(), signature, + new BigInteger(publicKey));*/ + boolean result = DataToolUtils.verifySignature(evidenceInfo.getCredentialHash(), signature, + new BigInteger(publicKey)); + + if (!result) { + logger.error("Public key does not match signature."); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_SIGNATURE_BROKEN); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("Passed-in signature illegal"); + return new ResponseData<>(false, ErrorCode.WEID_PUBLICKEY_INVALID); + } + } + } + + private ResponseData verifySignatureToSigner( + String rawData, + String signerWeId, + String secp256k1sig + ) { + try { + ResponseData innerResponseData = + weIdService.getWeIdDocument(signerWeId); + if (innerResponseData.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "Error occurred when fetching WeIdentity DID document for: {}, msg: {}", + signerWeId, innerResponseData.getErrorMessage()); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL); + } + WeIdDocument weIdDocument = innerResponseData.getResult(); + /*ErrorCode errorCode = DataToolUtils + .verifySecp256k1SignatureFromWeId(rawData, secp256k1sig, weIdDocument, null);*/ + ErrorCode errorCode = DataToolUtils + .verifySignatureFromWeId(rawData, secp256k1sig, weIdDocument, null); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, errorCode); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("error occurred during verifying signatures from chain: ", e); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_BASE_ERROR); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.EvidenceService#createEvidenceWithLogAndCustomKey( + * com.webank.weid.protocol.inf.Hashable, com.webank.weid.protocol.base.WeIdPrivateKey, + * java.lang.String) + */ + @Override + public ResponseData createEvidenceWithLogAndCustomKey( + Hashable object, + WeIdPrivateKey weIdPrivateKey, + String log, + String customKey) { + if (StringUtils.isEmpty(customKey) || DataToolUtils.isValidHash(customKey)) { + logger.error("Custom key must be non-empty and must not be of hash format."); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + if (!DataToolUtils.isUtf8String(log)) { + logger.error("Log format illegal."); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + if (StringUtils.isEmpty(log)) { + log = StringUtils.EMPTY; + } + if (!isChainStringLengthValid(log) || !isChainStringLengthValid(customKey)) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ON_CHAIN_STRING_TOO_LONG); + } + if (StringUtils.isEmpty(customKey)) { + customKey = StringUtils.EMPTY; + } + ResponseData hashResp = getHashValue(object); + String hashValue = hashResp.getResult(); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(StringUtils.EMPTY, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey)) { + return new ResponseData<>(StringUtils.EMPTY, + ErrorCode.WEID_PRIVATEKEY_INVALID); + } + String privateKey = weIdPrivateKey.getPrivateKey(); + try { + //String signature = DataToolUtils.secp256k1Sign(hashValue, new BigInteger(privateKey)); + String signature = DataToolUtils.SigBase64Serialization( + DataToolUtils.signToRsvSignature(hashValue, weIdPrivateKey.getPrivateKey()) + ); + Long timestamp = DateUtils.getCurrentTimeStamp(); + + if (processingMode == ProcessingMode.PERIODIC_AND_BATCH) { + String[] args = new String[7]; + args[0] = hashValue; + args[1] = signature; + args[2] = log; + args[3] = String.valueOf(timestamp); + args[4] = customKey; + args[5] = privateKey; + args[6] = String.valueOf(evidenceBlockchainService.getGroupId()); + String rawData = new StringBuffer() + .append(hashValue) + .append(signature) + .append(log) + .append(timestamp) + .append(customKey) + .append(WeIdUtils.getWeIdFromPrivateKey(privateKey)) + .append(evidenceBlockchainService.getGroupId()).toString(); + String hash = DataToolUtils.hash(rawData); + String requestId = new BigInteger(hash.substring(2), 16).toString(); + boolean isSuccess = BatchTransactionUtils + .writeTransaction(requestId, "createEvidenceWithCustomKey", args, + StringUtils.EMPTY); + if (isSuccess) { + return new ResponseData<>(hashValue, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(hashValue, ErrorCode.OFFLINE_EVIDENCE_SAVE_FAILED); + } + } + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.createEvidenceWithCustomKey( + hashValue, + signature, + log, + timestamp, + customKey, + privateKey + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(hashValue, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(StringUtils.EMPTY, resp.getErrorCode(), resp.getErrorMessage()); + } + } catch (Exception e) { + logger.error("create evidence failed due to system error. ", e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.CREDENTIAL_EVIDENCE_BASE_ERROR); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.service.rpc.EvidenceService#getEvidenceByCustomKey(java.lang.String) + */ + @Override + public ResponseData getEvidenceByCustomKey(String customKey) { + if (!isChainStringLengthValid(customKey)) { + return new ResponseData<>(null, ErrorCode.ON_CHAIN_STRING_TOO_LONG); + } + com.webank.weid.blockchain.protocol.response.ResponseData hashResp = evidenceBlockchainService.getInfoByCustomKey(customKey); + if(hashResp.getErrorCode() == ErrorCode.SUCCESS.getCode()){ + EvidenceInfo evidenceInfo = EvidenceInfo.fromBlockChain(hashResp.getResult()); + return new ResponseData<>(evidenceInfo, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, hashResp.getErrorCode(), hashResp.getErrorMessage()); + } + } + + private boolean isChainStringLengthValid(String string) { + return string.length() < WeIdConstant.ON_CHAIN_STRING_LENGTH; + } + + /** + * Revoke an evidence - which can be un-revoked. + * + * @param object the object + * @param weIdAuthentication the weid authentication + * @return true if yes, false otherwise, with error codes + */ + @Override + public ResponseData revoke(Hashable object, WeIdAuthentication weIdAuthentication) { + ResponseData hashResp = getHashValue(object); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(false, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + if (weIdAuthentication == null + || !WeIdUtils.isPrivateKeyValid(weIdAuthentication.getWeIdPrivateKey())) { + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + Long timestamp = DateUtils.getNoMillisecondTimeStamp(); + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.revoke( + hashResp.getResult(), + true, + timestamp, + weIdAuthentication.getWeIdPrivateKey().getPrivateKey() + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, resp.getErrorCode(), resp.getErrorMessage()); + } + } + + /** + * Revoke an evidence - which can be un-revoked. + * + * @param object the object + * @param weIdAuthentication the weid authentication + * @return true if yes, false otherwise, with error codes + */ + @Override + public ResponseData unRevoke(Hashable object, WeIdAuthentication weIdAuthentication) { + ResponseData hashResp = getHashValue(object); + if (StringUtils.isEmpty(hashResp.getResult())) { + return new ResponseData<>(false, hashResp.getErrorCode(), + hashResp.getErrorMessage()); + } + if (weIdAuthentication == null + || !WeIdUtils.isPrivateKeyValid(weIdAuthentication.getWeIdPrivateKey())) { + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); + } + Long timestamp = DateUtils.getNoMillisecondTimeStamp(); + com.webank.weid.blockchain.protocol.response.ResponseData resp = evidenceBlockchainService.revoke( + hashResp.getResult(), + false, + timestamp, + weIdAuthentication.getWeIdPrivateKey().getPrivateKey() + ); + if (resp.getErrorCode() == ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(false, resp.getErrorCode(), resp.getErrorMessage()); + } + } + + /** + * Check whether this evidence is revoked by this WeID. + * + * @param evidenceInfo the EvidenceInfo + * @param weId the signer WeID + * @return true if revoked, false otherwise + */ + @Override + public ResponseData isRevoked(EvidenceInfo evidenceInfo, String weId) { + if (evidenceInfo == null) { + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + Map evidenceSignInfos = evidenceInfo.getSignInfo(); + if (evidenceSignInfos == null || evidenceSignInfos.size() == 0 + || evidenceSignInfos.get(WeIdUtils.convertWeIdToAddress(weId)) == null) { + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(evidenceSignInfos.get(WeIdUtils.convertWeIdToAddress(weId)).getRevoked(), ErrorCode.SUCCESS); + } +} diff --git a/src/main/java/com/webank/weid/service/impl/PolicyServiceImpl.java b/src/main/java/com/webank/weid/service/impl/PolicyServiceImpl.java new file mode 100644 index 00000000..4b252a03 --- /dev/null +++ b/src/main/java/com/webank/weid/service/impl/PolicyServiceImpl.java @@ -0,0 +1,303 @@ +package com.webank.weid.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.webank.weid.service.local.PolicyServiceLocal; +import com.webank.weid.service.local.WeIdServiceLocal; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.protocol.response.RsvSignature; +import com.webank.weid.service.rpc.PolicyService; +import com.webank.weid.util.CredentialPojoUtils; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; + +/** + * Service implementations for operations on Evidence. + * + * @author chaoxinhu 2020.8 + */ + +public class PolicyServiceImpl implements PolicyService { + + private static final Logger logger = LoggerFactory.getLogger(PolicyServiceImpl.class); + private static com.webank.weid.blockchain.rpc.PolicyService policyBlockchainService; + + public PolicyServiceImpl(){ + policyBlockchainService = getPolicyService(); + } + + private static com.webank.weid.blockchain.rpc.PolicyService getPolicyService() { + if(policyBlockchainService != null) { + return policyBlockchainService; + } else { + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("blockchain")) { + return new com.webank.weid.blockchain.service.impl.PolicyServiceImpl(); + } else { + // default database + return new PolicyServiceLocal(); + } + } + } + /** + * Register Claim Policy on blockchain and assign it under a CPT ID. + * + * @param cptId CPT ID + * @param policyJson Policy Json file + * @param weIdAuthentication WeID auth + * @return claimPolicyId the Claim policy ID on-chain + */ + @Override + public ResponseData registerClaimPolicy(Integer cptId, String policyJson, + WeIdAuthentication weIdAuthentication) { + ResponseData policyIdResp = registerPolicyData(policyJson, weIdAuthentication); + if (policyIdResp.getResult() < 0) { + logger.error("Failed to register Claim Policy to blockchain."); + return policyIdResp; + } + // Append this claim policy id to the existing CPT's list + ResponseData> policiesResp = getClaimPoliciesFromCpt(cptId); + if (policiesResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("Failed to get this CPT's claim policy list."); + return new ResponseData<>(-1, policiesResp.getErrorCode(), + policiesResp.getErrorMessage()); + } + List policies = policiesResp.getResult(); + if (CollectionUtils.isEmpty(policies)) { + policies = new ArrayList<>(); + } + policies.add(policyIdResp.getResult()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + policyBlockchainService.putPolicyIntoCpt(cptId, policies, weIdAuthentication.getWeIdPrivateKey().getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(policyIdResp.getResult(), ErrorCode.SUCCESS); + /*ResponseData addResp = cptServiceEngine + .putPolicyIntoCpt(cptId, policies, weIdAuthentication.getWeIdPrivateKey()); + if (addResp.getResult() < 0) { + logger.error("Failed to add this policy ID {} into existing CPT ID's list: {}", + policyIdResp.getResult(), cptId); + return addResp; + } + return new ResponseData<>(policyIdResp.getResult(), ErrorCode.SUCCESS);*/ + } + + private ResponseData registerPolicyData(String policyJson, WeIdAuthentication auth) { + if (!DataToolUtils.isValidJsonStr(policyJson)) { + logger.error("[registerPolicy] input json format illegal."); + return new ResponseData<>(-1, ErrorCode.CPT_JSON_SCHEMA_INVALID); + } + ErrorCode errorCode = CredentialPojoUtils.isWeIdAuthenticationValid(auth); + if (errorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(-1, errorCode); + } + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(auth); + Map cptJsonSchemaMap = DataToolUtils.deserialize(policyJson, HashMap.class); + cptMapArgs.setCptJsonSchema(cptJsonSchemaMap); + WeIdPrivateKey weIdPrivateKey = auth.getWeIdPrivateKey(); + String cptJsonSchemaNew = DataToolUtils.serialize(cptMapArgs.getCptJsonSchema()); + RsvSignature rsvSignature = sign( + auth.getWeId(), + cptJsonSchemaNew, + weIdPrivateKey); + String address = WeIdUtils.convertWeIdToAddress(auth.getWeId()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + policyBlockchainService.registerPolicyData(address, cptJsonSchemaNew, RsvSignature.toBlockChain(rsvSignature), + weIdPrivateKey.getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + /*CptBaseInfo cptBaseInfo; + try { + cptBaseInfo = cptServiceEngine.registerCpt(address, cptJsonSchemaNew, rsvSignature, + weIdPrivateKey.getPrivateKey(), WeIdConstant.POLICY_DATA_INDEX).getResult(); + } catch (Exception e) { + logger.error("[register policy] register failed due to unknown error. ", e); + return new ResponseData<>(-1, ErrorCode.UNKNOW_ERROR.getCode(), + ErrorCode.UNKNOW_ERROR.getCodeDesc() + e.getMessage()); + } + if (cptBaseInfo != null && cptBaseInfo.getCptId() > 0) { + return new ResponseData<>(cptBaseInfo.getCptId(), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(-1, ErrorCode.UNKNOW_ERROR); + }*/ + } + + private RsvSignature sign( + String cptPublisher, + String jsonSchema, + WeIdPrivateKey cptPublisherPrivateKey) { + StringBuilder sb = new StringBuilder(); + sb.append(cptPublisher); + sb.append(WeIdConstant.PIPELINE); + sb.append(jsonSchema); + //SignatureData signatureData = DataToolUtils.secp256k1SignToSignature( + return DataToolUtils.signToRsvSignature( + sb.toString(), cptPublisherPrivateKey.getPrivateKey()); + } + + /** + * Get Claim Policy Json from blockchain given a policy ID. + * + * @param policyId the Claim Policy ID on-chain + * @return the claim Json + */ + @Override + public ResponseData getClaimPolicy(Integer policyId) { + if (policyId == null || policyId < 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + com.webank.weid.blockchain.protocol.response.ResponseData policyResp = + policyBlockchainService.getClaimPolicy(policyId); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed(policyResp.getResult()); + return new ResponseData<>(claimPolicy, ErrorCode.SUCCESS); + /*ResponseData policyResp = cptServiceEngine + .queryCpt(policyId, WeIdConstant.POLICY_DATA_INDEX); + if (policyResp.getResult() == null) { + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS.getCode(), + ErrorCode.CPT_NOT_EXISTS.getCodeDesc() + policyResp.getErrorMessage()); + } + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed( + DataToolUtils.serialize(policyResp.getResult().getCptJsonSchema())); + return new ResponseData<>(claimPolicy, ErrorCode.SUCCESS);*/ + } + + /** + * Get all claim policies from this CPT ID. + * + * @param cptId cpt id + * @return claim policies list + */ + @Override + public ResponseData> getClaimPoliciesFromCpt(Integer cptId) { + if (cptId == null || cptId < 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + com.webank.weid.blockchain.protocol.response.ResponseData> policyResp = + policyBlockchainService.getClaimPoliciesFromCpt(cptId); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + return new ResponseData<>(policyResp.getResult(), ErrorCode.SUCCESS); + //return cptServiceEngine.getPolicyFromCpt(cptId); + } + + /** + * Register Presentation Policy which contains a number of claim policies. + * + * @param claimPolicyIdList claim policies list + * @param weIdAuthentication weid auth + * @return the presentation policy id + */ + @Override + public ResponseData registerPresentationPolicy(List claimPolicyIdList, + WeIdAuthentication weIdAuthentication) { + ErrorCode errorCode = CredentialPojoUtils.isWeIdAuthenticationValid(weIdAuthentication); + if (errorCode != ErrorCode.SUCCESS) { + return new ResponseData<>(-1, errorCode); + } + com.webank.weid.blockchain.protocol.response.ResponseData policyResp = + policyBlockchainService.registerPresentationPolicy(claimPolicyIdList, weIdAuthentication.getWeIdPrivateKey().getPrivateKey()); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + return new ResponseData<>(policyResp.getResult(), ErrorCode.SUCCESS); + //return cptServiceEngine.putPolicyIntoPresentation(claimPolicyIdList, weIdAuthentication.getWeIdPrivateKey()); + } + + /** + * Get Presentation policies under this id from chain. + * + * @param presentationPolicyId presentation policy id + * @return the full presentation policy + */ + @Override + public ResponseData getPresentationPolicy(Integer presentationPolicyId) { + if (presentationPolicyId == null || presentationPolicyId < 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + com.webank.weid.blockchain.protocol.response.ResponseData policyResp = + policyBlockchainService.getPresentationPolicy(presentationPolicyId); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + PresentationPolicyE presentationPolicyE = PresentationPolicyE.fromBlockChain(policyResp.getResult()); + return new ResponseData<>(presentationPolicyE, ErrorCode.SUCCESS); + /*PresentationPolicyE presentationPolicy = cptServiceEngine + .getPolicyFromPresentation(presentationPolicyId) + .getResult(); + if (presentationPolicy == null) { + return new ResponseData<>(null, ErrorCode.CREDENTIAL_CLAIM_POLICY_NOT_EXIST); + } + Map policyMap = new HashMap<>(); + for (Map.Entry entry : presentationPolicy.getPolicy().entrySet()) { + policyMap.put(entry.getKey(), getClaimPolicy(entry.getKey()).getResult()); + } + presentationPolicy.setPolicy(policyMap); + return new ResponseData<>(presentationPolicy, ErrorCode.SUCCESS);*/ + } + + + /** + * Get all claim policies from chain. + * + * @param startPos start position + * @param num batch number + * @return claim policy list + */ + @Override + public ResponseData> getAllClaimPolicies(Integer startPos, Integer num) { + if (startPos < 0 || num < 1) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + com.webank.weid.blockchain.protocol.response.ResponseData> policyResp = + policyBlockchainService.getAllClaimPolicies(startPos, num); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + return new ResponseData<>(policyResp.getResult(), ErrorCode.SUCCESS); + //return cptServiceEngine.getCptIdList(startPos, num, WeIdConstant.POLICY_DATA_INDEX); + } + + @Override + public ResponseData getPolicyCount() { + com.webank.weid.blockchain.protocol.response.ResponseData policyResp = + policyBlockchainService.getPolicyCount(); + if (policyResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(policyResp.getErrorCode())); + } + return new ResponseData<>(policyResp.getResult(), ErrorCode.SUCCESS); + //return cptServiceEngine.getCptCount(WeIdConstant.POLICY_DATA_INDEX); + } +} diff --git a/src/main/java/com/webank/weid/service/impl/WeIdServiceImpl.java b/src/main/java/com/webank/weid/service/impl/WeIdServiceImpl.java index a1c3933c..81af7978 100644 --- a/src/main/java/com/webank/weid/service/impl/WeIdServiceImpl.java +++ b/src/main/java/com/webank/weid/service/impl/WeIdServiceImpl.java @@ -1,330 +1,118 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.service.impl; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; +package com.webank.weid.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.abi.EventEncoder; -import org.bcos.web3j.abi.TypeReference; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.Event; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; -import org.bcos.web3j.protocol.core.DefaultBlockParameterNumber; -import org.bcos.web3j.protocol.core.methods.response.EthBlock; -import org.bcos.web3j.protocol.core.methods.response.EthGetTransactionReceipt; -import org.bcos.web3j.protocol.core.methods.response.Log; -import org.bcos.web3j.protocol.core.methods.response.Transaction; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import com.webank.weid.config.ContractConfig; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; import com.webank.weid.constant.WeIdConstant; -import com.webank.weid.constant.WeIdEventConstant; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.exception.PrivateKeyIllegalException; -import com.webank.weid.protocol.base.AuthenticationProperty; -import com.webank.weid.protocol.base.PublicKeyProperty; -import com.webank.weid.protocol.base.ServiceProperty; -import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.AuthenticationArgs; import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; +import com.webank.weid.protocol.request.ServiceArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.WeIdService; -import com.webank.weid.service.BaseService; -import com.webank.weid.util.DataTypetUtils; -import com.webank.weid.util.DateUtils; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.protocol.response.WeIdListResult; +import com.webank.weid.service.local.WeIdServiceLocal; +import com.webank.weid.service.rpc.WeIdService; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.Multibase.Multibase; +import com.webank.weid.util.Multicodec.Multicodec; +import com.webank.weid.util.Multicodec.MulticodecEncoder; +import com.webank.weid.util.PropertyUtils; import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.fisco.bcos.sdk.model.CryptoType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Properties; /** * Service implementations for operations on WeIdentity DID. * - * @author tonychen 2018.10 + * @author afeexian 2022.08 */ -@Component -public class WeIdServiceImpl extends BaseService implements WeIdService { +public class WeIdServiceImpl implements WeIdService { /** * log4j object, for recording log. */ private static final Logger logger = LoggerFactory.getLogger(WeIdServiceImpl.class); - /** - * WeIdentity DID contract object, for calling weIdentity DID contract. - */ - private static WeIdContract weIdContract; - - /** - * WeIdentity DID contract address. - */ - private static String weIdContractAddress; - - /** - * The topic map. - */ - private static HashMap topicMap; - - /** - * Instantiates a new WeIdentity DID service. - */ - public WeIdServiceImpl() { - init(); - } - - private static void init() { - - // initialize the WeIdentity DID contract - ContractConfig config = context.getBean(ContractConfig.class); - weIdContractAddress = config.getWeIdAddress(); - weIdContract = (WeIdContract) getContractService(weIdContractAddress, WeIdContract.class); - - // initialize the event topic - initEventTopic(); - } - - private static void initEventTopic() { - - topicMap = new HashMap(); - final Event event = - new Event( - WeIdEventConstant.WEID_EVENT_ATTRIBUTE_CHANGE, - Arrays.>asList(new TypeReference
() { - }), - Arrays.>asList( - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - }, - new TypeReference() { - })); - topicMap.put(EventEncoder.encode(event), WeIdEventConstant.WEID_EVENT_ATTRIBUTE_CHANGE); - } + private static com.webank.weid.blockchain.rpc.WeIdService weIdBlockchainService; - private static int resolveAttributeEvent( - String weId, TransactionReceipt receipt, WeIdDocument result) { - - List eventlog = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isNotEmpty(eventlog)) { - WeIdAttributeChangedEventResponse res = eventlog.get(0); - String identity = res.identity.toString(); - if (null == result.getUpdated()) { - long timeStamp = res.updated.getValue().longValue(); - result.setUpdated(timeStamp); - } - String weAddress = WeIdUtils.convertWeIdToAddress(weId); - if (StringUtils.equals(weAddress, identity)) { - String key = DataTypetUtils.bytes32ToString(res.key); - String value = DataTypetUtils.dynamicBytesToString(res.value); - int previousBlock = res.previousBlock.getValue().intValue(); - buildupWeIdAttribute(key, value, weId, result); - return previousBlock; - } - } - return -1; + public WeIdServiceImpl(){ + weIdBlockchainService = getWeIdService(); } - private static void buildupWeIdAttribute( - String key, String value, String weId, WeIdDocument result) { - if (StringUtils.startsWith(key, WeIdConstant.WEID_DOC_PUBLICKEY_PREFIX)) { - buildWeIdPublicKeys(value, weId, result); - } else if (StringUtils.startsWith(key, WeIdConstant.WEID_DOC_AUTHENTICATE_PREFIX)) { - buildWeIdPublicKeys(value, weId, result); - buildWeIdAuthentication(value, weId, result); - } else if (StringUtils.startsWith(key, WeIdConstant.WEID_DOC_SERVICE_PREFIX)) { - buildWeIdService(key, value, weId, result); + private static com.webank.weid.blockchain.rpc.WeIdService getWeIdService() { + if(weIdBlockchainService != null) { + return weIdBlockchainService; } else { - buildWeIdAttributeDefault(key, value, weId, result); - } - } - - private static void buildWeIdPublicKeys(String value, String weId, WeIdDocument result) { - - logger.info("method buildWeIdPublicKeys() parameter::value:{}, weId:{}, " - + "result:{}", value, weId, result); - List pubkeyList = result.getPublicKey(); - for (PublicKeyProperty pr : pubkeyList) { - if (StringUtils.contains(value, pr.getPublicKey())) { - return; - } - } - PublicKeyProperty pubKey = new PublicKeyProperty(); - pubKey.setId( - new StringBuffer() - .append(weId) - .append("#keys-") - .append(result.getPublicKey().size()) - .toString()); - String[] publicKeyData = StringUtils.splitByWholeSeparator(value, "/"); - if (publicKeyData != null && publicKeyData.length == 2) { - pubKey.setPublicKey(publicKeyData[0]); - String weAddress = publicKeyData[1]; - String owner = WeIdUtils.convertAddressToWeId(weAddress); - pubKey.setOwner(owner); - } - result.getPublicKey().add(pubKey); - } - - private static void buildWeIdAuthentication(String value, String weId, WeIdDocument result) { - - logger.info("method buildWeIdAuthentication() parameter::value:{}, weId:{}, " - + "result:{}", value, weId, result); - AuthenticationProperty auth = new AuthenticationProperty(); - List keys = result.getPublicKey(); - List authList = result.getAuthentication(); - - for (PublicKeyProperty r : keys) { - if (StringUtils.contains(value, r.getPublicKey())) { - for (AuthenticationProperty ar : authList) { - if (StringUtils.equals(ar.getPublicKey(), r.getId())) { - return; - } - } - auth.setPublicKey(r.getId()); - result.getAuthentication().add(auth); - } - } - } - - private static void buildWeIdService(String key, String value, String weId, - WeIdDocument result) { - - logger.info("method buildWeIdService() parameter::key{}, value:{}, weId:{}, " - + "result:{}", key, value, weId, result); - String service = StringUtils.splitByWholeSeparator(key, "/")[2]; - List serviceList = result.getService(); - for (ServiceProperty sr : serviceList) { - if (StringUtils.equals(service, sr.getType())) { - return; - } - } - ServiceProperty serviceResult = new ServiceProperty(); - serviceResult.setType(service); - serviceResult.setServiceEndpoint(value); - result.getService().add(serviceResult); - } - - private static void buildWeIdAttributeDefault( - String key, String value, String weId, WeIdDocument result) { - - logger.info("method buildWeIdAttributeDefault() parameter::key{}, value:{}, weId:{}, " - + "result:{}", key, value, weId, result); - switch (key) { - case WeIdConstant.WEID_DOC_CREATED: - result.setCreated(Long.valueOf(value)); - break; - default: - break; - } - } - - private static int resolveEventLog( - String weId, Log log, TransactionReceipt receipt, WeIdDocument result) { - String topic = log.getTopics().get(0); - String event = topicMap.get(topic); - - if (StringUtils.isNotBlank(event)) { - switch (event) { - case WeIdEventConstant.WEID_EVENT_ATTRIBUTE_CHANGE: - return resolveAttributeEvent(weId, receipt, result); - default: + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("blockchain")) { + return new com.webank.weid.blockchain.service.impl.WeIdServiceImpl(); + } else { + // default database + return new WeIdServiceLocal(); } } - return -1; } - private static void resolveTransaction(String weId, int blockNumber, WeIdDocument result) { + /** + * Create a WeIdentity DID with null input param. + * + * @return the response data + */ + @Override + public ResponseData createWeId() { - if (blockNumber == 0) { - return; + CreateWeIdDataResult result = WeIdUtils.createWeId(); + if (Objects.isNull(result)) { + logger.error("Create weId failed."); + return new ResponseData<>(null, ErrorCode.WEID_KEYPAIR_CREATE_FAILED); } - EthBlock latestBlock = null; - try { - latestBlock = - getWeb3j().ethGetBlockByNumber(new DefaultBlockParameterNumber(blockNumber), true) - .send(); - } catch (IOException e) { + String address = WeIdUtils.convertWeIdToAddress(result.getWeId()); + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //在创建weid时默认添加一个id为#keys-[hash(publicKey)]的verification method + authenticationProperty.setId(result.getWeId() + "#keys-" + DataToolUtils.hash(result.getUserWeIdPublicKey().getPublicKey()).substring(58)); + //verification method controller默认为自己 + authenticationProperty.setController(result.getWeId()); + //这里把publicKey用multicodec编码,然后使用Multibase格式化,国密和非国密使用不同的编码 + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + result.getUserWeIdPublicKey().getPublicKey().getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + List authList = new ArrayList<>(); + authList.add(authenticationProperty.toString()); + List serviceList = new ArrayList<>(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setServiceEndpoint("https://github.com/WeBankBlockchain/WeIdentity"); + serviceProperty.setType("WeIdentity"); + serviceProperty.setId(authenticationProperty.getController() + '#' + DataToolUtils.hash(serviceProperty.getServiceEndpoint()).substring(58)); + serviceList.add(serviceProperty.toString()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = weIdBlockchainService.createWeId(address, authList, serviceList, result.getUserWeIdPrivateKey().getPrivateKey()); + //ResponseData innerResp = processCreateWeId(result.getWeId(), result.getUserWeIdPublicKey().getPublicKey(), result.getUserWeIdPrivateKey().getPrivateKey()); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { logger.error( - "[resolveTransaction]:get block by number :{} failed. Exception message:{}", - blockNumber, - e); - } - List transList = - latestBlock - .getBlock() - .getTransactions() - .stream() - .map(transactionResult -> (Transaction) transactionResult.get()) - .collect(Collectors.toList()); - - int previousBlock = 0; - for (Transaction transaction : transList) { - String transHash = transaction.getHash(); - try { - EthGetTransactionReceipt rec1 = getWeb3j().ethGetTransactionReceipt(transHash) - .send(); - TransactionReceipt receipt = rec1.getTransactionReceipt().get(); - List logs = rec1.getResult().getLogs(); - for (Log log : logs) { - int returnValue = resolveEventLog(weId, log, receipt, result); - if (returnValue != -1) { - previousBlock = returnValue; - } - } - } catch (IOException e) { - logger.error( - "[resolveTransaction]:get TransactionReceipt by hash :{} failed. Exception " - + "message:{}", - transHash, - e); - } - } - - resolveTransaction(weId, previousBlock, result); + "[createWeId] Create weId failed. error message is :{}", + innerResp.getErrorMessage() + ); + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); + } + return new ResponseData<>(result, ErrorCode.SUCCESS, innerResp.getTransactionInfo()); } /** @@ -333,62 +121,57 @@ private static void resolveTransaction(String weId, int blockNumber, WeIdDocumen * @return the response data */ @Override - public ResponseData createWeId() { - - ResponseData responseData = new ResponseData(); - CreateWeIdDataResult result = new CreateWeIdDataResult(); - ECKeyPair keyPair = null; - - try { - keyPair = Keys.createEcKeyPair(); - } catch (Exception e) { - logger.error("Create weId failed.", e); - return new ResponseData<>(null, ErrorCode.WEID_KEYPAIR_CREATE_FAILED); + public ResponseData createWeIdByPublicKey(WeIdPublicKey weIdPublicKey, WeIdPrivateKey weIdPrivateKey) { + if (!WeIdUtils.isPrivateKeyValid(weIdPrivateKey) || !WeIdUtils + .isPrivateKeyLengthValid(weIdPrivateKey.getPrivateKey())) { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PRIVATEKEY_INVALID); } - - String publicKey = String.valueOf(keyPair.getPublicKey()); - String privateKey = String.valueOf(keyPair.getPrivateKey()); - String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); - WeIdPublicKey userWeIdPublicKey = new WeIdPublicKey(); - userWeIdPublicKey.setPublicKey(publicKey); - result.setUserWeIdPublicKey(userWeIdPublicKey); - WeIdPrivateKey userWeIdPrivateKey = new WeIdPrivateKey(); - userWeIdPrivateKey.setPrivateKey(privateKey); - result.setUserWeIdPrivateKey(userWeIdPrivateKey); - result.setWeId(weId); - responseData.setResult(result); - - WeIdContract weIdContract = (WeIdContract) reloadContract( - weIdContractAddress, - privateKey, - WeIdContract.class); - Future future = - weIdContract.setAttribute( - new Address(WeIdUtils.convertWeIdToAddress(weId)), - DataTypetUtils.stringToBytes32(WeIdConstant.WEID_DOC_CREATED), - DataTypetUtils.stringToDynamicBytes(DateUtils.getCurrentTimeStampString()), - DateUtils.getCurrentTimeStampInt256()); - - try { - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List response = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isEmpty(response)) { + String privateKey = weIdPrivateKey.getPrivateKey(); + String publicKey = weIdPublicKey.getPublicKey(); + if (StringUtils.isNotBlank(publicKey)) { + String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); + ResponseData isWeIdExistResp = this.isWeIdExist(weId); + if (isWeIdExistResp.getResult() == null || isWeIdExistResp.getResult()) { + logger + .error("[createWeId]: create weid failed, the weid :{} is already exist", weId); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_ALREADY_EXIST); + } + String address = WeIdUtils.convertWeIdToAddress(weId); + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //在创建weid时默认添加一个id为#keys-[hash(publicKey)]的verification method + authenticationProperty.setId(weId + "#keys-" + DataToolUtils.hash(publicKey).substring(58)); + //verification method controller默认为自己 + authenticationProperty.setController(weId); + //这里把publicKey用multicodec编码,然后使用Multibase格式化,国密和非国密使用不同的编码 + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + publicKey.getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + List authList = new ArrayList<>(); + authList.add(authenticationProperty.toString()); + List serviceList = new ArrayList<>(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setServiceEndpoint("https://github.com/WeBankBlockchain/WeIdentity"); + serviceProperty.setType("WeIdentity"); + serviceProperty.setId(authenticationProperty.getController() + '#' + DataToolUtils.hash(serviceProperty.getServiceEndpoint()).substring(58)); + serviceList.add(serviceProperty.toString()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = weIdBlockchainService.createWeId(address, authList, serviceList, privateKey); + //ResponseData innerResp = processCreateWeId(weId, publicKey, privateKey); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { logger.error( - "The input private key does not match the current weid, operation of " - + "modifying weid is not allowed."); - return new ResponseData<>(null, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + "[createWeId]: create weid failed. error message is :{}, public key is {}", + innerResp.getErrorMessage(), + publicKey + ); + return new ResponseData<>(StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); } - } catch (InterruptedException | ExecutionException e) { - logger.error("Set authenticate failed. Error message :{}", e); - return new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(null, ErrorCode.TRANSACTION_TIMEOUT); - } catch (Exception e) { - return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + return new ResponseData<>(weId, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); + } else { + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PUBLICKEY_INVALID); } - return responseData; } /** @@ -400,62 +183,66 @@ public ResponseData createWeId() { @Override public ResponseData createWeId(CreateWeIdArgs createWeIdArgs) { - if (null == createWeIdArgs) { + if (createWeIdArgs == null) { logger.error("[createWeId]: input parameter createWeIdArgs is null."); return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); } - ResponseData responseData = new ResponseData(); - if (!WeIdUtils.isPrivateKeyValid(createWeIdArgs.getWeIdPrivateKey())) { + if (!WeIdUtils.isPrivateKeyValid(createWeIdArgs.getWeIdPrivateKey()) || !WeIdUtils + .isPrivateKeyLengthValid(createWeIdArgs.getWeIdPrivateKey().getPrivateKey())) { return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PRIVATEKEY_INVALID); } String privateKey = createWeIdArgs.getWeIdPrivateKey().getPrivateKey(); String publicKey = createWeIdArgs.getPublicKey(); if (StringUtils.isNotBlank(publicKey)) { - if (!WeIdUtils.isKeypairMatch(privateKey, publicKey)) { + if (!WeIdUtils.isKeypairMatch(new BigInteger(privateKey), publicKey)) { return new ResponseData<>( - StringUtils.EMPTY, ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED); + StringUtils.EMPTY, + ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED + ); } String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); ResponseData isWeIdExistResp = this.isWeIdExist(weId); - if (null == isWeIdExistResp.getResult() || isWeIdExistResp.getResult()) { + if (isWeIdExistResp.getResult() == null || isWeIdExistResp.getResult()) { + logger + .error("[createWeId]: create weid failed, the weid :{} is already exist", weId); return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_ALREADY_EXIST); } - responseData.setResult(weId); - try { - WeIdContract weIdContract = (WeIdContract) reloadContract( - weIdContractAddress, - privateKey, - WeIdContract.class); - Future future = - weIdContract.setAttribute( - new Address(WeIdUtils.convertWeIdToAddress(weId)), - DataTypetUtils.stringToBytes32(WeIdConstant.WEID_DOC_CREATED), - DataTypetUtils.stringToDynamicBytes(DateUtils.getCurrentTimeStampString()), - DateUtils.getCurrentTimeStampInt256()); - - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List response = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isEmpty(response)) { - return new ResponseData<>(StringUtils.EMPTY, - ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); - } - } catch (InterruptedException | ExecutionException e) { - logger.error("create weid failed. Error message :{}", e); + String address = WeIdUtils.convertWeIdToAddress(weId); + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //在创建weid时默认添加一个id为#keys-[hash(publicKey)]的verification method + authenticationProperty.setId(weId + "#keys-" + DataToolUtils.hash(publicKey).substring(58)); + //verification method controller默认为自己 + authenticationProperty.setController(weId); + //这里把publicKey用multicodec编码,然后使用Multibase格式化,国密和非国密使用不同的编码 + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + publicKey.getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + List authList = new ArrayList<>(); + authList.add(authenticationProperty.toString()); + List serviceList = new ArrayList<>(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setServiceEndpoint("https://github.com/WeBankBlockchain/WeIdentity"); + serviceProperty.setType("WeIdentity"); + serviceProperty.setId(authenticationProperty.getController() + '#' + DataToolUtils.hash(serviceProperty.getServiceEndpoint()).substring(58)); + serviceList.add(serviceProperty.toString()); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = weIdBlockchainService.createWeId(address, authList, serviceList, privateKey); + //ResponseData innerResp = processCreateWeId(weId, publicKey, privateKey); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[createWeId]: create weid failed. error message is :{}, public key is {}", + innerResp.getErrorMessage(), + publicKey + ); return new ResponseData<>(StringUtils.EMPTY, - ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); - } catch (TimeoutException e) { - return new ResponseData<>(StringUtils.EMPTY, ErrorCode.TRANSACTION_TIMEOUT); - } catch (PrivateKeyIllegalException e) { - return new ResponseData<>(StringUtils.EMPTY, e.getErrorCode()); - } catch (Exception e) { - return new ResponseData<>(StringUtils.EMPTY, ErrorCode.UNKNOW_ERROR); + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); } + return new ResponseData<>(weId, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); } else { return new ResponseData<>(StringUtils.EMPTY, ErrorCode.WEID_PUBLICKEY_INVALID); } - return responseData; } /** @@ -466,38 +253,42 @@ public ResponseData createWeId(CreateWeIdArgs createWeIdArgs) { */ @Override public ResponseData getWeIdDocument(String weId) { - ResponseData responseData = new ResponseData(); - WeIdDocument result = new WeIdDocument(); - result.setId(weId); if (!WeIdUtils.isWeIdValid(weId)) { logger.error("Input weId : {} is invalid.", weId); - responseData = new ResponseData<>(null, ErrorCode.WEID_INVALID); - return responseData; + return new ResponseData<>(null, ErrorCode.WEID_INVALID); } - - int latestBlockNumber = 0; - try { - String identityAddr = WeIdUtils.convertWeIdToAddress(weId); - latestBlockNumber = - weIdContract - .getLatestRelatedBlock(new Address(identityAddr)) - .get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS) - .getValue() - .intValue(); - if (0 == latestBlockNumber) { - return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); - } - } catch (InterruptedException | ExecutionException e) { - logger.error("Set weId service failed. Error message :{}", e); - return responseData = new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(null, ErrorCode.TRANSACTION_TIMEOUT); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = weIdBlockchainService.getWeIdDocument(weId); + //ResponseData weIdDocResp = weIdServiceEngine.getWeIdDocument(weId); + if(innerResp.getErrorCode() == ErrorCode.SUCCESS.getCode() && innerResp.getResult() != null){ + WeIdDocument weIdDocument = WeIdDocument.fromBlockChain(innerResp.getResult()); + return new ResponseData<>(weIdDocument, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, innerResp.getErrorCode(), innerResp.getErrorMessage()); } + } - resolveTransaction(weId, latestBlockNumber, result); - responseData.setResult(result); - return responseData; + /** + * Get a WeIdentity DID Document Metadata. + * + * @param weId the WeIdentity DID + * @return the WeIdentity DID document + */ + @Override + public ResponseData getWeIdDocumentMetadata(String weId) { + + if (!WeIdUtils.isWeIdValid(weId)) { + logger.error("Input weId : {} is invalid.", weId); + return new ResponseData<>(null, ErrorCode.WEID_INVALID); + } + //ResponseData weIdDocResp = weIdServiceEngine.getWeIdDocumentMetadata(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = weIdBlockchainService.getWeIdDocumentMetadata(weId); + if(innerResp.getErrorCode() == ErrorCode.SUCCESS.getCode()){ + WeIdDocumentMetadata weIdDocResp = WeIdDocumentMetadata.fromBlockChain(innerResp.getResult()); + return new ResponseData<>(weIdDocResp, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, innerResp.getErrorCode(), innerResp.getErrorMessage()); + } } /** @@ -512,17 +303,22 @@ public ResponseData getWeIdDocumentJson(String weId) { ResponseData responseData = this.getWeIdDocument(weId); WeIdDocument result = responseData.getResult(); - if (null == result) { + if (result == null) { return new ResponseData<>( - StringUtils.EMPTY, responseData.getErrorCode(), responseData.getErrorMessage()); + StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(responseData.getErrorCode()) + ); } ObjectMapper mapper = new ObjectMapper(); String weIdDocument; try { weIdDocument = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result); } catch (Exception e) { + logger.error("write object to String fail.", e); return new ResponseData<>( - StringUtils.EMPTY, responseData.getErrorCode(), responseData.getErrorMessage()); + StringUtils.EMPTY, + ErrorCode.getTypeByErrorCode(responseData.getErrorCode()) + ); } weIdDocument = new StringBuffer() @@ -530,276 +326,497 @@ public ResponseData getWeIdDocumentJson(String weId) { .insert(1, WeIdConstant.WEID_DOC_PROTOCOL_VERSION) .toString(); - ResponseData ResponseDataJson = new ResponseData(); - ResponseDataJson.setResult(weIdDocument); - ResponseDataJson.setErrorCode(responseData.getErrorCode()); - ResponseDataJson.setErrorMessage(responseData.getErrorMessage()); + ResponseData responseDataJson = new ResponseData(); + responseDataJson.setResult(weIdDocument); + responseDataJson.setErrorCode(ErrorCode.getTypeByErrorCode(responseData.getErrorCode())); - return ResponseDataJson; + return responseDataJson; } /** - * Set Public Key. + * Set service properties. * - * @param setPublicKeyArgs the set public key args - * @return the response data + * @param weId the WeID to set service to + * @param serviceArgs your service name and endpoint + * @param privateKey the private key + * @return true if the "set" operation succeeds, false otherwise. */ @Override - public ResponseData setPublicKey(SetPublicKeyArgs setPublicKeyArgs) { - - if (!verifySetPublicKeyArgs(setPublicKeyArgs)) { - logger.error("[setPublicKey]: input parameter setPublicKeyArgs is illegal."); + public ResponseData setService(String weId, ServiceArgs serviceArgs, + WeIdPrivateKey privateKey) { + if (!verifyServiceArgs(serviceArgs)) { + logger.error("[setService]: input parameter setServiceArgs is illegal."); return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); } - if (!WeIdUtils.isPrivateKeyValid(setPublicKeyArgs.getUserWeIdPrivateKey())) { + if (!WeIdUtils.isPrivateKeyValid(privateKey)) { return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); } - ResponseData responseData = new ResponseData(); - String weId = setPublicKeyArgs.getWeId(); - String weAddress = WeIdUtils.convertWeIdToAddress(weId); - if (StringUtils.isEmpty(weAddress)) { - logger.error("setPublicKey: weId : {} is invalid.", weId); + return processSetService( + privateKey.getPrivateKey(), + weId, + serviceArgs); + + } + + /** + * Check if WeIdentity DID exists on Chain. + * + * @param weId the WeIdentity DID + * @return true if exists, false otherwise + */ + @Override + public ResponseData isWeIdExist(String weId) { + if (!WeIdUtils.isWeIdValid(weId)) { + logger.error("[isWeIdExist] check weid failed. weid : {} is invalid.", weId); return new ResponseData<>(false, ErrorCode.WEID_INVALID); } - String owner = setPublicKeyArgs.getOwner(); - if (StringUtils.isEmpty(owner)) { - owner = weAddress; - } else { - if (WeIdUtils.isWeIdValid(owner)) { - owner = WeIdUtils.convertWeIdToAddress(owner); - } else { - logger.error("setPublicKey: owner : {} is invalid.", owner); - return new ResponseData<>(false, ErrorCode.WEID_INVALID); - } + //return weIdServiceEngine.isWeIdExist(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.isWeIdExist(weId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); } - String pubKey = setPublicKeyArgs.getPublicKey(); - String attributeKey = - new StringBuffer() - .append(WeIdConstant.WEID_DOC_PUBLICKEY_PREFIX) - .append("/") - .append(setPublicKeyArgs.getType()) - .append("/") - .append("base64") - .toString(); - String privateKey = setPublicKeyArgs.getUserWeIdPrivateKey().getPrivateKey(); - try { - WeIdContract weIdContract = (WeIdContract) reloadContract( - weIdContractAddress, - privateKey, - WeIdContract.class); - Future future = - weIdContract.setAttribute( - new Address(weAddress), - DataTypetUtils.stringToBytes32(attributeKey), - DataTypetUtils.stringToDynamicBytes( - new StringBuffer().append(pubKey).append("/").append(owner).toString()), - DateUtils.getCurrentTimeStampInt256()); - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List response = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isNotEmpty(response)) { - return new ResponseData<>(true, ErrorCode.SUCCESS); - } else { - return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); - } - } catch (InterruptedException | ExecutionException e) { - logger.error("Set public key failed. Error message :{}", e); - responseData = new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); - } catch (PrivateKeyIllegalException e) { - return new ResponseData<>(false, e.getErrorCode()); - } catch (Exception e) { - return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); - } - return responseData; + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); } - private boolean verifySetPublicKeyArgs(SetPublicKeyArgs setPublicKeyArgs) { - - return !(null == setPublicKeyArgs - || null == setPublicKeyArgs.getType() - || null == setPublicKeyArgs.getUserWeIdPrivateKey() - || null == setPublicKeyArgs.getPublicKey() - ); + /** + * Check if WeIdentity DID is deactivated on Chain. + * + * @param weId the WeIdentity DID + * @return true if is deactivated, false otherwise + */ + @Override + public ResponseData isDeactivated(String weId) { + if (!WeIdUtils.isWeIdValid(weId)) { + logger.error("[isWeIdExist] check weid failed. weid : {} is invalid.", weId); + return new ResponseData<>(false, ErrorCode.WEID_INVALID); + } + //return weIdServiceEngine.isDeactivated(weId); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.isDeactivated(weId); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(true, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); } /** - * Set Service. + * Set authentications in WeIdentity DID. * - * @param setServiceArgs the set service args - * @return the response data + * @param weId the WeID to set auth to + * @param authenticationArgs A public key is needed + * @param privateKey the private key + * @return true if the "set" operation succeeds, false otherwise. */ @Override - public ResponseData setService(SetServiceArgs setServiceArgs) { + public ResponseData setAuthentication( + String weId, + AuthenticationArgs authenticationArgs, + WeIdPrivateKey privateKey){ - if (!verifySetServiceArgs(setServiceArgs)) { - logger.error("[setService]: input parameter setServiceArgs is illegal."); + if (!verifyAuthenticationArgs(authenticationArgs)) { + logger.error("[setAuthentication]: input parameter setAuthenticationArgs is illegal."); return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); } - if (!WeIdUtils.isPrivateKeyValid(setServiceArgs.getUserWeIdPrivateKey())) { + if (!WeIdUtils.isPrivateKeyValid(privateKey)) { return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); } - ResponseData responseData = new ResponseData<>(); - String weId = setServiceArgs.getWeId(); - String serviceType = setServiceArgs.getType(); - String serviceEndpoint = setServiceArgs.getServiceEndpoint(); + return processSetAuthentication( + authenticationArgs, + privateKey.getPrivateKey(), + weId); + } + + private ResponseData processSetAuthentication( + AuthenticationArgs authenticationArgs, + String privateKey, + String weId) { if (WeIdUtils.isWeIdValid(weId)) { - String privateKey = setServiceArgs.getUserWeIdPrivateKey().getPrivateKey(); - try { - WeIdContract weIdContract = (WeIdContract) reloadContract( - weIdContractAddress, - privateKey, - WeIdContract.class); - Future future = - weIdContract.setAttribute( - new Address(WeIdUtils.convertWeIdToAddress(weId)), - DataTypetUtils.stringToBytes32( - WeIdConstant.WEID_DOC_SERVICE_PREFIX + "/" + serviceType), - DataTypetUtils.stringToDynamicBytes(serviceEndpoint), - DateUtils.getCurrentTimeStampInt256()); - - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List response = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isNotEmpty(response)) { - return new ResponseData<>(true, ErrorCode.SUCCESS); - } else { - return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + //检查目标WeId是否存在和是否被注销 + ResponseData isWeIdExistResp = this.isWeIdExist(weId); + if (isWeIdExistResp.getResult() == null || !isWeIdExistResp.getResult()) { + logger.error("[setAuthentication]: failed, the weid :{} does not exist", + weId); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + ResponseData isDeactivatedResp = this.isDeactivated(weId); + if (isDeactivatedResp.getResult() == null || isDeactivatedResp.getResult()) { + logger.error("[setAuthentication]: failed, the weid :{} has been deactivated", + weId); + return new ResponseData<>(false, ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + //检查authentication的controller WeId是否存在和是否被注销 + if (StringUtils.isEmpty(authenticationArgs.getController())) { + authenticationArgs.setController(weId); + } + if (!WeIdUtils.isWeIdValid(authenticationArgs.getController())) { + logger.error("[setAuthentication]: controller : {} is invalid.", authenticationArgs.getController()); + return new ResponseData<>(false, ErrorCode.WEID_INVALID); + } + isWeIdExistResp = this.isWeIdExist(authenticationArgs.getController()); + if (isWeIdExistResp.getResult() == null || !isWeIdExistResp.getResult()) { + logger.error("[setAuthentication]: failed, the controller weid :{} does not exist", + authenticationArgs.getController()); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + isDeactivatedResp = this.isDeactivated(authenticationArgs.getController()); + if (isDeactivatedResp.getResult() == null || isDeactivatedResp.getResult()) { + logger.error("[setAuthentication]: failed, the controller weid :{} has been deactivated", + authenticationArgs.getController()); + return new ResponseData<>(false, ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + WeIdDocument weIdDocument = this.getWeIdDocument(weId).getResult(); + for(int i=0; i(false, ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS); } - } catch (InterruptedException | ExecutionException e) { - responseData = new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); + if(!StringUtils.isEmpty(authenticationArgs.getId()) && authenticationArgs.getId().equals(weIdDocument.getAuthentication().get(i).getId())){ + logger.error("[setAuthentication]: failed, the Authentication with id :{} exists", + authenticationArgs.getId()); + return new ResponseData<>(false, ErrorCode.AUTHENTICATION_METHOD_ID_EXISTS); + } + } + AuthenticationProperty authenticationProperty = new AuthenticationProperty(); + //如果用户没有指定method id,则系统分配 + authenticationProperty.setId(authenticationArgs.getId()); + if(StringUtils.isBlank(authenticationArgs.getId())){ + authenticationProperty.setId(weId + "#keys-" + DataToolUtils.hash(authenticationArgs.getPublicKey()).substring(58)); + } + authenticationProperty.setController(authenticationArgs.getController()); + byte[] publicKeyEncode = MulticodecEncoder.encode(DataToolUtils.cryptoType == CryptoType.ECDSA_TYPE? Multicodec.ED25519_PUB:Multicodec.SM2_PUB, + authenticationArgs.getPublicKey().getBytes(StandardCharsets.UTF_8)); + authenticationProperty.setPublicKeyMultibase(Multibase.encode(Multibase.Base.Base58BTC, publicKeyEncode)); + + List authentication = weIdDocument.getAuthentication(); + authentication.add(authenticationProperty); + weIdDocument.setAuthentication(authentication); + /*try { + return weIdServiceEngine + .updateWeId(weIdDocument, + WeIdUtils.convertWeIdToAddress(weId), + privateKey); } catch (PrivateKeyIllegalException e) { + logger.error("Set authenticate with private key exception. Error message :{}", e); return new ResponseData<>(false, e.getErrorCode()); } catch (Exception e) { - logger.error("Set weId service failed. Error message :{}", e); + logger.error("Set authenticate failed. Error message :{}", e); return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + }*/ + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.updateWeId(WeIdDocument.toBlockChain(weIdDocument), privateKey, WeIdUtils.convertWeIdToAddress(weId)); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[setAuthentication]: set authenticate failed. error message is :{}", + innerResp.getErrorMessage() + ); + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); } + return new ResponseData<>(true, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); } else { - responseData = new ResponseData<>(false, ErrorCode.WEID_INVALID); + logger.error("Set authenticate failed. weid : {} is invalid.", weId); + return new ResponseData<>(false, ErrorCode.WEID_INVALID); } - return responseData; - } - - private boolean verifySetServiceArgs(SetServiceArgs setServiceArgs) { - - return !(null == setServiceArgs - || null == setServiceArgs.getType() - || null == setServiceArgs.getUserWeIdPrivateKey() - || null == setServiceArgs.getServiceEndpoint() - ); } /** - * Set Authentication. + * Remove an authentication tag in WeID document only - will not affect its public key. * - * @param setAuthenticationArgs the set authentication args - * @return the response data + * @param weId the WeID to remove auth from + * @param authenticationArgs A public key is needed + * @param privateKey the private key + * @return true if succeeds, false otherwise */ @Override - public ResponseData setAuthentication(SetAuthenticationArgs setAuthenticationArgs) { - - if (!verifySetAuthenticationArgs(setAuthenticationArgs)) { - logger.error("[setAuthentication]: input parameter setAuthenticationArgs is illegal."); + public ResponseData revokeAuthentication( + String weId, + AuthenticationArgs authenticationArgs, + WeIdPrivateKey privateKey) { + + if (!verifyAuthenticationArgs(authenticationArgs)) { + logger + .error("[revokeAuthentication]: input parameter setAuthenticationArgs is illegal."); return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); } - if (!WeIdUtils.isPrivateKeyValid(setAuthenticationArgs.getUserWeIdPrivateKey())) { + if (!WeIdUtils.isPrivateKeyValid(privateKey)) { return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_INVALID); } - ResponseData responseData = new ResponseData<>(); - String weId = setAuthenticationArgs.getWeId(); if (WeIdUtils.isWeIdValid(weId)) { - String weAddress = WeIdUtils.convertWeIdToAddress(weId); - - String owner = setAuthenticationArgs.getOwner(); - if (StringUtils.isEmpty(owner)) { - owner = weAddress; - } else { - if (WeIdUtils.isWeIdValid(owner)) { - owner = WeIdUtils.convertWeIdToAddress(owner); - } else { - logger.error("setPublicKey: owner : {} is invalid.", owner); - return new ResponseData<>(false, ErrorCode.WEID_INVALID); + ResponseData isWeIdExistResp = this.isWeIdExist(weId); + if (isWeIdExistResp.getResult() == null || !isWeIdExistResp.getResult()) { + logger.error("[revokeAuthentication]: failed, the weid :{} does not exist", weId); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + WeIdDocument weIdDocument = this.getWeIdDocument(weId).getResult(); + List authentication = weIdDocument.getAuthentication(); + if(!StringUtils.isEmpty(authenticationArgs.getPublicKey())){ + for(int i=0; i(false, e.getErrorCode()); + } catch (Exception e) { + logger.error("remove authenticate failed. Error message :{}", e); + return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + }*/ + authentication.remove(i); + weIdDocument.setAuthentication(authentication); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.updateWeId(WeIdDocument.toBlockChain(weIdDocument), privateKey.getPrivateKey(), WeIdUtils.convertWeIdToAddress(weId)); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[revokeAuthentication]: remove authenticate failed. error message is :{}", + innerResp.getErrorMessage() + ); + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); + } + return new ResponseData<>(true, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); + } + logger.error("[revokeAuthentication]: failed, the Authentication with publicKey :{} not exists", + authenticationArgs.getPublicKey()); } } - String privateKey = setAuthenticationArgs.getUserWeIdPrivateKey().getPrivateKey(); - try { - WeIdContract weIdContract = (WeIdContract) reloadContract( - weIdContractAddress, - privateKey, - WeIdContract.class); - Future future = - weIdContract.setAttribute( - new Address(weAddress), - DataTypetUtils.stringToBytes32(WeIdConstant.WEID_DOC_AUTHENTICATE_PREFIX), - DataTypetUtils.stringToDynamicBytes( - new StringBuffer() - .append(setAuthenticationArgs.getPublicKey()) - .append("/") - .append(owner) - .toString()), - DateUtils.getCurrentTimeStampInt256()); - TransactionReceipt receipt = - future.get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - List response = - WeIdContract.getWeIdAttributeChangedEvents(receipt); - if (CollectionUtils.isNotEmpty(response)) { - responseData = new ResponseData<>(true, ErrorCode.SUCCESS); - } else { - return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + if(!StringUtils.isEmpty(authenticationArgs.getId())){ + for(int i=0; i(false, e.getErrorCode()); + } catch (Exception e) { + logger.error("remove authenticate failed. Error message :{}", e); + return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + }*/ + authentication.remove(i); + weIdDocument.setAuthentication(authentication); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.updateWeId(WeIdDocument.toBlockChain(weIdDocument), privateKey.getPrivateKey(), WeIdUtils.convertWeIdToAddress(weId)); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[revokeAuthentication]: remove authenticate failed. error message is :{}", + innerResp.getErrorMessage() + ); + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); + } + return new ResponseData<>(true, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); + } + logger.error("[revokeAuthentication]: failed, the Authentication with id :{} not exists", + authenticationArgs.getId()); } - } catch (InterruptedException | ExecutionException e) { - logger.error("Set authenticate failed. Error message :{}", e); - responseData = new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); + } + logger.error("[revokeAuthentication]: failed, the Authentication not exists"); + return new ResponseData<>(false, ErrorCode.AUTHENTICATION_METHOD_NOT_EXISTS); + } else { + logger.error("revokeAuthentication failed. weid : {} is invalid.", weId); + return new ResponseData<>(false, ErrorCode.WEID_INVALID); + } + } + + private boolean verifyServiceArgs(ServiceArgs serviceArgs) { + + return !(serviceArgs == null + || StringUtils.isBlank(serviceArgs.getType()) + || StringUtils.isBlank(serviceArgs.getServiceEndpoint())); + } + + /*private ResponseData processCreateWeId( + String weId, + String publicKey, + String privateKey) { + + String address = WeIdUtils.convertWeIdToAddress(weId); + try { + return weIdServiceEngine.createWeId(address, publicKey, privateKey); + } catch (PrivateKeyIllegalException e) { + logger.error("[createWeId] create weid failed because privateKey is illegal. ", + e); + return new ResponseData<>(false, e.getErrorCode()); + } catch (LoadContractException e) { + logger.error("[createWeId] create weid failed because Load Contract with " + + "exception. ", + e); + return new ResponseData<>(false, e.getErrorCode()); + } catch (Exception e) { + logger.error("[createWeId] create weid failed with exception. ", e); + return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + } + }*/ + + private boolean verifyAuthenticationArgs(AuthenticationArgs authenticationArgs) { + + return !(authenticationArgs == null + || StringUtils.isEmpty(authenticationArgs.getPublicKey()) + || !(isPublicKeyStringValid(authenticationArgs.getPublicKey()))); + } + + private boolean isPublicKeyStringValid(String pubKey) { + // Allow base64, rsa (alphaNum) and bigInt + return (DataToolUtils.isValidBase64String(pubKey) + // || StringUtils.isAlphanumeric(pubKey) + || NumberUtils.isDigits(pubKey)); + } + + private ResponseData processSetService( + String privateKey, + String weId, + ServiceArgs serviceArgs) { + if (WeIdUtils.isWeIdValid(weId)) { + ResponseData isWeIdExistResp = this.isWeIdExist(weId); + if (isWeIdExistResp.getResult() == null || !isWeIdExistResp.getResult()) { + logger.error("[SetService]: failed, the weid :{} does not exist", weId); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + WeIdDocument weIdDocument = this.getWeIdDocument(weId).getResult(); + List service = weIdDocument.getService(); + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setType(serviceArgs.getType()); + serviceProperty.setServiceEndpoint(serviceArgs.getServiceEndpoint()); + if(weIdDocument.getService().size()==0){ + if(StringUtils.isEmpty(serviceArgs.getId())){ + serviceProperty.setId(weId + '#' + DataToolUtils.hash(serviceArgs.getServiceEndpoint())); + }else{ + serviceProperty.setId(serviceArgs.getId()); + } + }else{ + if(StringUtils.isEmpty(serviceArgs.getId())){ + serviceProperty.setId(weId + '#' + DataToolUtils.hash(serviceArgs.getServiceEndpoint()).substring(58)); + }else{ + for(int i=0; i(false, ErrorCode.SERVICE_METHOD_ID_EXISTS); + } + } + serviceProperty.setId(serviceArgs.getId()); + } + } + service.add(serviceProperty); + weIdDocument.setService(service); + /*try { + return weIdServiceEngine + .updateWeId(weIdDocument, + WeIdUtils.convertWeIdToAddress(weId), + privateKey); } catch (PrivateKeyIllegalException e) { + logger + .error("[setService] set service failed because privateKey is illegal. ", + e); return new ResponseData<>(false, e.getErrorCode()); } catch (Exception e) { + logger.error("[setService] set service failed. Error message :{}", e); return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + }*/ + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.updateWeId(WeIdDocument.toBlockChain(weIdDocument), privateKey, WeIdUtils.convertWeIdToAddress(weId)); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[createWeId]: set service failed. error message is :{}", + innerResp.getErrorMessage() + ); + return new ResponseData<>(false, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode()), + innerResp.getTransactionInfo()); } + return new ResponseData<>(true, + ErrorCode.SUCCESS, + innerResp.getTransactionInfo()); } else { - responseData = new ResponseData<>(false, ErrorCode.WEID_INVALID); + logger.error("[setService] set service failed, weid -->{} is invalid.", weId); + return new ResponseData<>(false, ErrorCode.WEID_INVALID); } - return responseData; } - private boolean verifySetAuthenticationArgs(SetAuthenticationArgs setAuthenticationArgs) { + @Override + public ResponseData> getWeIdList( + Integer first, + Integer last + ) { + /*try { + logger.info("[getWeIdList] begin get weIdList, first index = {}, last index = {}", + first, + last + ); + return weIdServiceEngine.getWeIdList(first, last); + } catch (Exception e) { + logger.error("[getWeIdList] get weIdList failed with exception. ", e); + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + }*/ + com.webank.weid.blockchain.protocol.response.ResponseData> innerResp = + weIdBlockchainService.getWeIdList(first, last); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(null, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); + } - return !(null == setAuthenticationArgs - || null == setAuthenticationArgs.getType() - || null == setAuthenticationArgs.getUserWeIdPrivateKey() - || StringUtils.isEmpty(setAuthenticationArgs.getPublicKey()) - ); + @Override + public ResponseData getWeIdCount() { + //return weIdServiceEngine.getWeIdCount(); + com.webank.weid.blockchain.protocol.response.ResponseData innerResp = + weIdBlockchainService.getWeIdCount(); + if (innerResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return new ResponseData<>(-1, + ErrorCode.getTypeByErrorCode(innerResp.getErrorCode())); + } + return new ResponseData<>(innerResp.getResult(), ErrorCode.SUCCESS); } - /** - * Check if WeIdentity DID exists on Chain. - * - * @param weId the WeIdentity DID - * @return true if exists, false otherwise - */ @Override - public ResponseData isWeIdExist(String weId) { - if (!WeIdUtils.isWeIdValid(weId)) { - return new ResponseData<>(false, ErrorCode.WEID_INVALID); - } - try { - Bool isExist = weIdContract - .isIdentityExist(new Address(WeIdUtils.convertWeIdToAddress(weId))) - .get(WeIdConstant.TRANSACTION_RECEIPT_TIMEOUT, TimeUnit.SECONDS); - Boolean result = isExist.getValue(); - return new ResponseData<>(result, ErrorCode.SUCCESS); - } catch (InterruptedException | ExecutionException e1) { - return new ResponseData<>(false, ErrorCode.TRANSACTION_EXECUTE_ERROR); - } catch (TimeoutException e) { - return new ResponseData<>(false, ErrorCode.TRANSACTION_TIMEOUT); - } catch (Exception e) { - return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); - } + public ResponseData getWeIdListByPubKeyList(List pubKeyList) { + if (pubKeyList == null || pubKeyList.size() == 0) { + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + WeIdListResult weIdListResult = new WeIdListResult(); + weIdListResult.setWeIdList(new ArrayList<>()); + weIdListResult.setErrorCodeList(new ArrayList<>()); + ResponseData responseData = new ResponseData(); + pubKeyList.forEach(weIdPublicKey -> { + String weId = WeIdUtils.convertPublicKeyToWeId(weIdPublicKey.getPublicKey()); + if (StringUtils.isBlank(weId)) { + weIdListResult.getWeIdList().add(null); + weIdListResult.getErrorCodeList().add(ErrorCode.WEID_PUBLICKEY_INVALID.getCode()); + } else { + if (this.isWeIdExist(weId).getResult()) { + weIdListResult.getWeIdList().add(weId); + weIdListResult.getErrorCodeList().add(ErrorCode.SUCCESS.getCode()); + } else { + weIdListResult.getWeIdList().add(null); + weIdListResult.getErrorCodeList().add( + ErrorCode.WEID_PUBLIC_KEY_NOT_EXIST.getCode()); + } + } + }); + responseData.setResult(weIdListResult); + return responseData; } } diff --git a/src/main/java/com/webank/weid/service/local/AuthorityIssuerServiceLocal.java b/src/main/java/com/webank/weid/service/local/AuthorityIssuerServiceLocal.java new file mode 100644 index 00000000..e73c4172 --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/AuthorityIssuerServiceLocal.java @@ -0,0 +1,581 @@ +package com.webank.weid.service.local; + +import com.webank.weid.blockchain.constant.ChainType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.constant.WeIdConstant; +import com.webank.weid.blockchain.protocol.base.AuthorityIssuer; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.IssuerType; +import com.webank.weid.blockchain.protocol.request.RegisterAuthorityIssuerArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.blockchain.rpc.AuthorityIssuerService; +import com.webank.weid.blockchain.service.impl.AuthorityIssuerServiceImpl; +import com.webank.weid.blockchain.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.contract.deploy.AddressProcess; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.service.local.role.RoleController; +import com.webank.weid.suite.persistence.*; +import com.webank.weid.suite.persistence.mysql.SqlDomain; +import com.webank.weid.suite.persistence.mysql.SqlExecutor; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Component("authorityIssuerServiceLocal") +public class AuthorityIssuerServiceLocal implements AuthorityIssuerService { + private static final Logger logger = LoggerFactory.getLogger(AuthorityIssuerServiceLocal.class); + + private static Persistence dataDriver; + private static PersistenceType persistenceType; + WeIdServiceLocal weIdServiceLocal = new WeIdServiceLocal(); + RoleController roleController = new RoleController(); + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + /** + * add a new Authority Issuer on Chain. + * + * @param args the args + * @return the Boolean response data + */ + @Override + public ResponseData addAuthorityIssuer(RegisterAuthorityIssuerArgs args) { + AuthorityIssuer authorityIssuer = args.getAuthorityIssuer(); + if(!com.webank.weid.blockchain.util.WeIdUtils.isPrivateKeyValid(args.getWeIdPrivateKey())){ + logger.error("[addAuthorityIssuer] the privateKey of issuer is not valid"); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + //如果不存在该weId则报错 + if(!weIdServiceLocal.isWeIdExist(authorityIssuer.getWeId()).getResult()){ + logger.error("[addAuthorityIssuer] the weid of authority does not exist on blockchain"); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + if(getDataDriver().getAuthorityIssuerByWeId(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, authorityIssuer.getWeId()).getResult() != null){ + logger.error("[addAuthorityIssuer] Authority Issuer already exist"); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST); + } + if(getDataDriver().getAuthorityIssuerByName(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, authorityIssuer.getName()).getResult() != null){ + logger.error("[addAuthorityIssuer] Authority Issuer's name already exist"); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + } + String extraStr = null; + if(authorityIssuer.getExtraStr32().size() != 0){ + extraStr = authorityIssuer.getExtraStr32().get(0); + if(authorityIssuer.getExtraStr32().size() > 1) { + for(int i = 1; i < authorityIssuer.getExtraStr32().size(); i++){ + extraStr = extraStr + ',' + authorityIssuer.getExtraStr32().get(i); + } + } + } + String extraInt = null; + if(authorityIssuer.getExtraInt().size() != 0) { + extraInt = String.valueOf(authorityIssuer.getExtraInt().get(0)); + if (authorityIssuer.getExtraInt().size() > 1) { + for (int i = 1; i < authorityIssuer.getExtraInt().size(); i++) { + extraInt = extraInt + ',' + authorityIssuer.getExtraInt().get(i); + } + } + } + ResponseData resp = + getDataDriver().addAuthorityIssuer( + DataDriverConstant.LOCAL_AUTHORITY_ISSUER, + authorityIssuer.getWeId(), + authorityIssuer.getName(), + authorityIssuer.getDescription(), + authorityIssuer.getAccValue(), + extraStr, + extraInt + ); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addAuthorityIssuer] save addAuthorityIssuer to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Remove a new Authority Issuer on Chain. + * + * @param weId the weId + * @param privateKey the privateKey + * @return the Boolean response data + */ + @Override + public ResponseData removeAuthorityIssuer(String weId, String privateKey) { + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_AUTHORITY_ISSUER)){ + logger.error("[removeAuthorityIssuer] operator has not permission to removeAuthorityIssuer"); + return new ResponseData<>(false, ErrorCode.CONTRACT_ERROR_NO_PERMISSION); + } + if(getDataDriver().getAuthorityIssuerByWeId(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, weId).getResult() == null){ + logger.error("[removeAuthorityIssuer] Authority Issuer not exist"); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + if(roleController.checkRole(weId, RoleController.ROLE_AUTHORITY_ISSUER) && !roleController.removeRole(WeIdUtils.getWeIdFromPrivateKey(privateKey), weId, RoleController.ROLE_AUTHORITY_ISSUER)) { + logger.error("[removeAuthorityIssuer] remove AuthorityIssuer role from db failed."); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + ResponseData resp = + getDataDriver().removeAuthorityIssuer( + DataDriverConstant.LOCAL_AUTHORITY_ISSUER, + weId); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeAuthorityIssuer] delete addAuthorityIssuer from db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Check whether the given weId is an authority issuer. + * + * @param addr the address of WeIdentity DID + * @return the Boolean response data + */ + @Override + public ResponseData isAuthorityIssuer(String addr) { + if(!RoleController.checkRole(WeIdUtils.convertAddressToWeId(addr), RoleController.ROLE_AUTHORITY_ISSUER)){ + return new ResponseData<>(false, ErrorCode.SUCCESS); + } + if(getDataDriver().getAuthorityIssuerByWeId(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, WeIdUtils.convertAddressToWeId(addr)).getResult() == null){ + return new ResponseData<>(false, ErrorCode.SUCCESS); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Recognize this WeID to be an authority issuer. + * + * @param stage the stage that weather recognize + * @param addr the address of WeIdentity DID + * @param privateKey the private key set + * @return true if succeeds, false otherwise + */ + @Override + public ResponseData recognizeWeId(Boolean stage, String addr, String privateKey) { + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_AUTHORITY_ISSUER)){ + logger.error("[recognizeWeId] operator has not permission to recognizeWeId"); + return new ResponseData<>(false, ErrorCode.CONTRACT_ERROR_NO_PERMISSION); + } + if(getDataDriver().getAuthorityIssuerByWeId(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, WeIdUtils.convertAddressToWeId(addr)).getResult() == null){ + logger.error("[recognizeWeId] Authority Issuer not exist"); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + if(stage){ + if(!roleController.addRole(WeIdUtils.getWeIdFromPrivateKey(privateKey), WeIdUtils.convertAddressToWeId(addr), RoleController.ROLE_AUTHORITY_ISSUER)){ + logger.error("[recognizeWeId] add AuthorityIssuer role to db failed."); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + ResponseData resp = getDataDriver().updateAuthorityIssuer(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, WeIdUtils.convertAddressToWeId(addr), 1); + if(resp.getErrorCode() != ErrorCode.SUCCESS.getCode()){ + logger.error("[recognizeWeId] update AuthorityIssuer recognize to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + if(!roleController.removeRole(WeIdUtils.getWeIdFromPrivateKey(privateKey), WeIdUtils.convertAddressToWeId(addr), RoleController.ROLE_AUTHORITY_ISSUER)){ + logger.error("[recognizeWeId] remove AuthorityIssuer role from db failed."); + return new ResponseData<>(false, ErrorCode.AUTHORITY_ISSUER_ERROR); + } + ResponseData resp = getDataDriver().updateAuthorityIssuer(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, WeIdUtils.convertAddressToWeId(addr), 0); + if(resp.getErrorCode() != ErrorCode.SUCCESS.getCode()){ + logger.error("[recognizeWeId] update AuthorityIssuer deRecognize to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + } + + /** + * Query the authority issuer information given weId. + * + * @param weId the WeIdentity DID + * @return the AuthorityIssuer response data + */ + @Override + public ResponseData queryAuthorityIssuerInfo(String weId) { + ResponseData resultData = new ResponseData(); + AuthorityIssuer result = new AuthorityIssuer(); + AuthorityIssuerInfo authorityIssuerInfo = getDataDriver().getAuthorityIssuerByWeId(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, weId).getResult(); + if(authorityIssuerInfo == null){ + logger.error("[queryAuthorityIssuerInfo] Authority Issuer not exist"); + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + result.setWeId(weId); + result.setName(authorityIssuerInfo.getName()); + result.setAccValue(authorityIssuerInfo.getAcc_value()); + result.setCreated(authorityIssuerInfo.getCreated().getTime()); + result.setDescription(authorityIssuerInfo.getDescription()); + result.setRecognized(authorityIssuerInfo.getRecognize()==1); + if(authorityIssuerInfo.getExtra_str() != null){ + result.setExtraStr32(Arrays.asList(authorityIssuerInfo.getExtra_str().split(","))); + } + if(authorityIssuerInfo.getExtra_int() != null){ + List extraInt = new ArrayList<>(); + for(String i:authorityIssuerInfo.getExtra_int().split(",")){ + extraInt.add(Integer.valueOf(i)); + } + result.setExtraInt(extraInt); + } + resultData.setResult(result); + return resultData; + } + + /** + * Get all of the authority issuer. + * + * @param index start position + * @param num number of returned authority issuer in this request + * @return Execution result + */ + @Override + public ResponseData> getAuthorityIssuerAddressList(Integer index, Integer num) { + try { + return getDataDriver().getWeIdList( + DataDriverConstant.LOCAL_AUTHORITY_ISSUER, + index, + index + num); + } catch (Exception e) { + logger.error("[getAuthorityIssuerAddressList] getAuthorityIssuerAddressList has error, Error Message:{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * Register a new issuer type. + * + * @param privateKey the caller + * @param issuerType the specified issuer type + * @return Execution result + */ + @Override + public ResponseData registerIssuerType( + String privateKey, + String issuerType + ) { + if (StringUtils.isEmpty(issuerType) || StringUtils.isEmpty(privateKey)) { + logger.error("[registerIssuerType] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if(getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult() != null){ + logger.error("[registerIssuerType] issuerType already exist on chain"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS); + } + ResponseData resp = + getDataDriver().addSpecificType( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + issuerType, + WeIdUtils.getWeIdFromPrivateKey(privateKey)); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerIssuerType] save IssuerType to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Marked an issuer as the specified issuer type. + * + * @param privateKey the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param issuerAddress the address of the issuer who will be marked as a specific issuer type + * @return Execution result + */ + @Override + public ResponseData addIssuer( + String privateKey, + String issuerType, + String issuerAddress + ) { + if (StringUtils.isEmpty(issuerType) || StringUtils.isEmpty(issuerAddress) ||StringUtils.isEmpty(privateKey)) { + logger.error("[addIssuer] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_KEY_CPT)){ + logger.error("[addIssuer] operator has not permission to addIssuer"); + return new ResponseData<>(false, ErrorCode.CONTRACT_ERROR_NO_PERMISSION); + } + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(specificTypeValue == null){ + logger.error("[addIssuer] issuerType not exist on chain"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + //判断这个issuerType是否已经有fellow + if(specificTypeValue.getFellow() != null){ + //判断是否已经存在这个issuer + String[] fellows = specificTypeValue.getFellow().split(","); + for (String obj : fellows) { + if(obj.equals(issuerAddress)) return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS); + } + ResponseData resp = + getDataDriver().updateSpecificTypeFellow( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + issuerType, + specificTypeValue.getFellow()+','+issuerAddress); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addIssuer] addIssuer to issuerType failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } else { + ResponseData resp = + getDataDriver().updateSpecificTypeFellow( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + issuerType, + issuerAddress); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addIssuer] addIssuer to issuerType failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + } + + /** + * Removed an issuer from the specified issuer list. + * + * @param privateKey the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param issuerAddress the address of the issuer who will be marked as a specific issuer type + * @return Execution result + */ + @Override + public ResponseData removeIssuer( + String privateKey, + String issuerType, + String issuerAddress + ) { + if (StringUtils.isEmpty(issuerType) || StringUtils.isEmpty(issuerAddress) ||StringUtils.isEmpty(privateKey)) { + logger.error("[removeIssuer] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_KEY_CPT)){ + logger.error("[removeIssuer] operator has not permission to removeIssuer"); + return new ResponseData<>(false, ErrorCode.CONTRACT_ERROR_NO_PERMISSION); + } + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(!isSpecificTypeIssuer(issuerType, issuerAddress).getResult()){ + logger.error("[removeIssuer] issuerAddress not the fellow of issuerType"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + String[] fellows = specificTypeValue.getFellow().split(","); + List fellowList = new ArrayList<>(Arrays.asList(fellows)); + fellowList.remove(issuerAddress); + String newFellow = fellowList.get(0); + if(fellowList.size() != 1) { + for(int i = 1; i < fellowList.size(); i++){ + newFellow = newFellow + ',' + fellowList.get(i); + } + } + ResponseData resp = + getDataDriver().updateSpecificTypeFellow( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + issuerType, + newFellow); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeIssuer] removeIssuer from issuerType failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Check if the given WeId is belonging to a specific issuer type. + * + * @param issuerType the issuer type + * @param address the address + * @return true if yes, false otherwise + */ + @Override + public ResponseData isSpecificTypeIssuer( + String issuerType, + String address + ) { + if (StringUtils.isEmpty(issuerType) || StringUtils.isEmpty(address)) { + logger.error("[isSpecificTypeIssuer] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(specificTypeValue == null){ + logger.error("[isSpecificTypeIssuer] issuerType not exist on chain"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + if(specificTypeValue.getFellow().equals(StringUtils.EMPTY)){ + logger.error("[isSpecificTypeIssuer] issuerType has not fellow"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + String[] fellows = specificTypeValue.getFellow().split(","); + for (String obj : fellows) { + if(obj.equals(address)) return new ResponseData<>(true, ErrorCode.SUCCESS); + } + return new ResponseData<>(false, ErrorCode.SUCCESS); + } + + /** + * Get all specific typed issuer in a list. + * + * @param issuerType the issuer type + * @param index the start position index + * @param num the number of issuers + * @return the list + */ + @Override + public ResponseData> getAllSpecificTypeIssuerList( + String issuerType, + Integer index, + Integer num + ) { + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(specificTypeValue == null || specificTypeValue.getFellow().equals(StringUtils.EMPTY)){ + logger.error("[getAllSpecificTypeIssuerList] issuerType not exist on chain"); + return new ResponseData<>(null, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + String[] fellows = specificTypeValue.getFellow().split(","); + List fellowList = Arrays.asList(fellows); + if (fellows.length<=index) { + logger.error("[getAllSpecificTypeIssuerList] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + if(fellows.length>index + num - 1){ + return new ResponseData<>(fellowList.subList(index, index + num), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(fellowList.subList(index, fellows.length - 1), ErrorCode.SUCCESS); + } + } + + @Override + public ResponseData getWeIdFromOrgId(String orgId) { + if (StringUtils.isEmpty(orgId)) { + logger.error("[getWeIdFromOrgId] input argument is illegal"); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + AuthorityIssuerInfo authorityIssuerInfo = getDataDriver().getAuthorityIssuerByName(DataDriverConstant.LOCAL_AUTHORITY_ISSUER, orgId).getResult(); + if (WeIdConstant.EMPTY_ADDRESS.equalsIgnoreCase(WeIdUtils.convertWeIdToAddress(authorityIssuerInfo.getWeid()))) { + return new ResponseData<>(StringUtils.EMPTY, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + return new ResponseData<>(authorityIssuerInfo.getWeid(), ErrorCode.SUCCESS); + } + + @Override + public ResponseData getIssuerCount() { + try { + return getDataDriver().getAuthorityIssuerCount(DataDriverConstant.LOCAL_AUTHORITY_ISSUER); + } catch (Exception e) { + logger.error("[getIssuerCount] getIssuerCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData getRecognizedIssuerCount() { + try { + return getDataDriver().getRecognizedIssuerCount(DataDriverConstant.LOCAL_AUTHORITY_ISSUER); + } catch (Exception e) { + logger.error("[getRecognizedIssuerCount] getRecognizedIssuerCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData getSpecificTypeIssuerSize(String issuerType) { + if (StringUtils.isEmpty(issuerType)) { + logger.error("[getSpecificTypeIssuerSize] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(specificTypeValue == null){ + logger.error("[getSpecificTypeIssuerSize] issuerType not exist on chain"); + return new ResponseData<>(null, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + if(specificTypeValue.getFellow() == null){ + logger.error("[getSpecificTypeIssuerSize] issuerType has not fellow"); + return new ResponseData<>(0, ErrorCode.SUCCESS); + } + String[] fellows = specificTypeValue.getFellow().split(","); + return new ResponseData<>(fellows.length, ErrorCode.SUCCESS); + } + + @Override + public ResponseData getIssuerTypeCount() { + try { + return getDataDriver().getIssuerTypeCount(DataDriverConstant.LOCAL_SPECIFIC_ISSUER); + } catch (Exception e) { + logger.error("[getIssuerTypeCount] getIssuerTypeCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData removeIssuerType( + String privateKey, + String issuerType + ) { + if (StringUtils.isEmpty(issuerType) ||StringUtils.isEmpty(privateKey)) { + logger.error("[removeIssuerType] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, issuerType).getResult(); + if(specificTypeValue.getFellow() != null){ + logger.error("[removeIssuerType] has issuer in the specific issuer type"); + return new ResponseData<>(false, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_EXIST_ISSUER); + } + if(!specificTypeValue.getOwner().equals(WeIdUtils.getWeIdFromPrivateKey(privateKey))){ + logger.error("[removeIssuerType] no permission to removeIssuerType"); + return new ResponseData<>(false, ErrorCode.CONTRACT_ERROR_NO_PERMISSION); + } + ResponseData resp = + getDataDriver().removeSpecificType( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + issuerType); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeIssuerType] delete IssuerType from db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + @Override + public ResponseData> getIssuerTypeList(Integer index, Integer num) { + try { + List typeNameList= getDataDriver().getIssuerTypeList( + DataDriverConstant.LOCAL_SPECIFIC_ISSUER, + index, + index + num).getResult(); + List issuerTypeList = new ArrayList<>(); + for (String typeName : typeNameList) { + SpecificTypeValue specificTypeValue = getDataDriver().getSpecificType(DataDriverConstant.LOCAL_SPECIFIC_ISSUER, typeName).getResult(); + IssuerType issuerType = new IssuerType(); + issuerType.setTypeName(typeName); + issuerType.setCreated(specificTypeValue.getCreated().getTime()); + issuerType.setOwner(specificTypeValue.getOwner()); + issuerTypeList.add(issuerType); + } + return new ResponseData<>(issuerTypeList, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[getIssuerTypeList] getIssuerTypeList has error, Error Message:{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + +} diff --git a/src/main/java/com/webank/weid/service/local/CptServiceLocal.java b/src/main/java/com/webank/weid/service/local/CptServiceLocal.java new file mode 100644 index 00000000..7e07ebfd --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/CptServiceLocal.java @@ -0,0 +1,335 @@ +package com.webank.weid.service.local; + +import com.webank.wedpr.selectivedisclosure.CredentialTemplateEntity; +import com.webank.wedpr.selectivedisclosure.proto.AttributeTemplate; +import com.webank.wedpr.selectivedisclosure.proto.TemplatePublicKey; +import com.webank.weid.blockchain.constant.ChainType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.constant.WeIdConstant; +import com.webank.weid.blockchain.protocol.base.Cpt; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.blockchain.protocol.response.RsvSignature; +import com.webank.weid.blockchain.rpc.CptService; +import com.webank.weid.blockchain.service.impl.CptServiceImpl; +import com.webank.weid.util.JsonUtil; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.protocol.base.GlobalStatus; +import com.webank.weid.service.local.role.RoleController; +import com.webank.weid.suite.persistence.CptValue; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.PropertyUtils; +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component("cptServiceLocal") +public class CptServiceLocal implements CptService { + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(CptServiceLocal.class); + + private static Persistence dataDriver; + private static PersistenceType persistenceType; + public static Integer AUTHORITY_ISSUER_START_ID = 1000; + public static Integer NONE_AUTHORITY_ISSUER_START_ID = 2000000; + WeIdServiceLocal weIdServiceLocal = new WeIdServiceLocal(); + AuthorityIssuerServiceLocal authorityIssuerServiceLocal = new AuthorityIssuerServiceLocal(); + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + /** + * Register a new CPT with a pre-set CPT ID, to the blockchain. + * + * @param address the address of creator + * @param cptJsonSchemaNew the new cptJsonSchema + * @param rsvSignature the rsvSignature of cptJsonSchema + * @param privateKey the decimal privateKey of creator + * @param cptId the CPT ID + * @return response data + */ + public ResponseData registerCpt( + String address, + String cptJsonSchemaNew, + RsvSignature rsvSignature, + String privateKey, + Integer cptId) { + if (StringUtils.isEmpty(address) || StringUtils.isEmpty(cptJsonSchemaNew) || StringUtils.isEmpty(privateKey)) { + logger.error("[registerCpt] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + //如果不存在该weId则报错 + if(!weIdServiceLocal.isWeIdExist(WeIdUtils.convertAddressToWeId(address)).getResult()){ + logger.error("[registerCpt] the weid of publisher does not exist on blockchain"); + return new ResponseData<>(null, ErrorCode.CPT_PUBLISHER_NOT_EXIST); + } + if(getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult() != null){ + logger.error("[registerCpt] cpt already exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_ALREADY_EXIST); + } + if(cptId < AUTHORITY_ISSUER_START_ID){ + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_AUTHORITY_ISSUER)){ + logger.error("[registerCpt] operator has not committee member permission to registerCpt"); + return new ResponseData<>(null, ErrorCode.CPT_NO_PERMISSION); + } + }else if(cptId < NONE_AUTHORITY_ISSUER_START_ID){ + if(!RoleController.checkPermission(WeIdUtils.getWeIdFromPrivateKey(privateKey), RoleController.MODIFY_KEY_CPT)){ + logger.error("[registerCpt] operator has not authority issuer permission to registerCpt"); + return new ResponseData<>(null, ErrorCode.CPT_NO_PERMISSION); + } + } + ResponseData resp = + getDataDriver().addCpt( + DataDriverConstant.LOCAL_CPT, + cptId, + address, + null, + cptJsonSchemaNew, + com.webank.weid.blockchain.util.DataToolUtils.SigBase64Serialization(rsvSignature)); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerCpt] save cpt to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } + + /** + * This is used to register a new CPT to the blockchain. + * + * @param address the address of creator + * @param cptJsonSchemaNew the new cptJsonSchema + * @param rsvSignature the rsvSignature of cptJsonSchema + * @param privateKey the decimal privateKey of creator + * @return the response data + */ + public ResponseData registerCpt( + String address, + String cptJsonSchemaNew, + RsvSignature rsvSignature, + String privateKey) { + if (StringUtils.isEmpty(address) || StringUtils.isEmpty(cptJsonSchemaNew) || StringUtils.isEmpty(privateKey)) { + logger.error("[registerCpt] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + //如果不存在该weId则报错 + if(!weIdServiceLocal.isWeIdExist(WeIdUtils.convertAddressToWeId(address)).getResult()){ + logger.error("[registerCpt] the weid of publisher does not exist on blockchain"); + return new ResponseData<>(null, ErrorCode.CPT_PUBLISHER_NOT_EXIST); + } + int cptId = getCptId(address); + + ResponseData resp = + getDataDriver().addCpt( + DataDriverConstant.LOCAL_CPT, + cptId, + address, + null, + cptJsonSchemaNew, + com.webank.weid.blockchain.util.DataToolUtils.SigBase64Serialization(rsvSignature)); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerCpt] save cpt to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } + + public int getCptId(String address) { + GlobalStatus globalStatus = GlobalStatus.readStatusFromFile("global.status"); + if(authorityIssuerServiceLocal.isAuthorityIssuer(address).getResult()){ + int cptId = globalStatus.getAuthority_issuer_current_cpt_id(); + while (getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult() != null) { + cptId++; + } + globalStatus.setAuthority_issuer_current_cpt_id(cptId); + GlobalStatus.storeStatusToFile(globalStatus, "global.status"); + if(cptId > NONE_AUTHORITY_ISSUER_START_ID) cptId = 0; + return cptId; + } else { + int cptId = globalStatus.getNone_authority_issuer_current_cpt_id(); + while (getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult() != null) { + cptId++; + } + globalStatus.setNone_authority_issuer_current_cpt_id(cptId); + GlobalStatus.storeStatusToFile(globalStatus, "global.status"); + return cptId; + } + } + + /** + * this is used to query cpt with the latest version which has been registered. + * + * @param cptId the cpt id + * @return the response data + */ + public ResponseData queryCpt(Integer cptId) { + try { + CptValue cptValue = getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult(); + if(cptValue == null){ + logger.error("[queryCpt] cpt not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + Cpt cpt = new Cpt(); + cpt.setCptId(cptId); + cpt.setCptVersion(cptValue.getCpt_version()); + cpt.setCptPublisher(cptValue.getPublisher()); + cpt.setCptSignature(cptValue.getCpt_signature()); + Map jsonSchemaMap = DataToolUtils + .deserialize(cptValue.getCpt_schema(), HashMap.class); + cpt.setCptJsonSchema(jsonSchemaMap); + return new ResponseData<>(cpt, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[queryCpt] execute failed. Error message :{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * This is used to update a CPT data which has been register. + * + * @param address the address of creator + * @param cptJsonSchemaNew the new cptJsonSchema + * @param rsvSignature the rsvSignature of cptJsonSchema + * @param privateKey the decimal privateKey of creator + * @param cptId the CPT ID + * @return the response data + */ + public ResponseData updateCpt(String address, + String cptJsonSchemaNew, + RsvSignature rsvSignature, + String privateKey, + Integer cptId) { + if (StringUtils.isEmpty(address) || StringUtils.isEmpty(cptJsonSchemaNew) || StringUtils.isEmpty(privateKey)) { + logger.error("[updateCpt] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + if(!weIdServiceLocal.isWeIdExist(com.webank.weid.util.WeIdUtils.convertAddressToWeId(address)).getResult()){ + logger.error("[updateCpt] the weid of publisher does not exist on blockchain"); + return new ResponseData<>(null, ErrorCode.CPT_PUBLISHER_NOT_EXIST); + } + CptValue cptValue = getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult(); + if(cptValue == null){ + logger.error("[updateCpt] cpt not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + if(!cptValue.getPublisher().equals(address)){ + logger.error("[updateCpt] cpt publisher of this cpt is not equal to the address"); + return new ResponseData<>(null, ErrorCode.CPT_NO_PERMISSION); + } + ResponseData resp = + getDataDriver().updateCpt( + DataDriverConstant.LOCAL_CPT, + cptId, + cptValue.getCpt_version() + 1, + address, + cptValue.getDescription(), + cptJsonSchemaNew, + com.webank.weid.blockchain.util.DataToolUtils.SigBase64Serialization(rsvSignature)); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[updateCpt] update cpt to db failed."); + throw new DatabaseException("database error!"); + } + CptBaseInfo cptBaseInfo = new CptBaseInfo(); + cptBaseInfo.setCptId(cptId); + cptBaseInfo.setCptVersion(cptValue.getCpt_version() + 1); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS); + } + + @Override + public ResponseData putCredentialTemplate(Integer cptId, String credentialPublicKey, String credentialKeyCorrectnessProof) { + if (StringUtils.isEmpty(credentialPublicKey) || StringUtils.isEmpty(credentialKeyCorrectnessProof)) { + logger.error("[putCredentialTemplate] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + CptValue cptValue = getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult(); + if(cptValue == null){ + logger.error("[putCredentialTemplate] cpt not exist on chain"); + return new ResponseData<>(false, ErrorCode.CPT_NOT_EXISTS); + } + ResponseData resp = + getDataDriver().updateCredentialTemplate( + DataDriverConstant.LOCAL_CPT, + cptId, + credentialPublicKey, + credentialKeyCorrectnessProof); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[putCredentialTemplate] update credential template to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + @Override + public ResponseData queryCredentialTemplate(Integer cptId) { + try { + CptValue cptValue = getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult(); + if(cptValue == null){ + logger.error("[queryCredentialTemplate] cpt not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + CredentialTemplateEntity credentialTemplateEntity = new CredentialTemplateEntity(); + TemplatePublicKey pubKey = TemplatePublicKey.newBuilder().setCredentialPublicKey(cptValue.getCredential_publicKey()).build(); + credentialTemplateEntity.setPublicKey(pubKey); + credentialTemplateEntity.setCredentialKeyCorrectnessProof(cptValue.getCredential_proof()); + Map cptInfo = DataToolUtils + .deserialize(cptValue.getCpt_schema(), HashMap.class); + List attrList; + attrList = JsonUtil.extractCptProperties(cptInfo); + AttributeTemplate.Builder builder = AttributeTemplate.newBuilder(); + for (String attr : attrList) { + builder.addAttributeKey(attr); + } + AttributeTemplate attributes = builder.build(); + credentialTemplateEntity.setCredentialSchema(attributes); + return new ResponseData<>(credentialTemplateEntity, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[queryCredentialTemplate] execute failed. Error message :{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData> getCptIdList(Integer startPos, Integer num) { + try { + return getDataDriver().getCptIdList( + DataDriverConstant.LOCAL_CPT, + startPos, + startPos + num); + } catch (Exception e) { + logger.error("[getCptIdList] getCptIdList has error, Error Message:{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData getCptCount() { + try { + return getDataDriver().getCptCount(DataDriverConstant.LOCAL_CPT); + } catch (Exception e) { + logger.error("[getCptCount] getCptCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + +} diff --git a/src/main/java/com/webank/weid/service/local/EvidenceServiceLocal.java b/src/main/java/com/webank/weid/service/local/EvidenceServiceLocal.java new file mode 100644 index 00000000..3d3387fc --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/EvidenceServiceLocal.java @@ -0,0 +1,441 @@ +package com.webank.weid.service.local; + +import com.webank.weid.blockchain.constant.ChainType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.EvidenceInfo; +import com.webank.weid.blockchain.protocol.base.EvidenceSignInfo; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.blockchain.rpc.EvidenceService; +import com.webank.weid.blockchain.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.service.local.role.RoleController; +import com.webank.weid.suite.persistence.EvidenceValue; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component("evidenceServiceLocal") +public class EvidenceServiceLocal implements EvidenceService { + private static final Logger logger = LoggerFactory.getLogger(EvidenceServiceLocal.class); + + private static Persistence dataDriver; + private static PersistenceType persistenceType; + public String groupId = "1"; + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + @Override + public String getGroupId(){ + return this.groupId; + } + + @Override + public ResponseData createEvidence( + String hashValue, + String signature, + String log, + Long timestamp, + String privateKey + ) { + if (StringUtils.isEmpty(hashValue) || StringUtils.isEmpty(log) || StringUtils.isEmpty(signature) || StringUtils.isEmpty(privateKey)) { + logger.error("[createEvidence] input argument is illegal"); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.ILLEGAL_INPUT); + } + if(getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValue).getResult() != null) { + logger.error("[createEvidence] evidence with the hash value already existed"); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.CREDENTIAL_EVIDENCE_ALREADY_EXISTS); + } + ResponseData resp = + getDataDriver().addEvidenceByHash( + DataDriverConstant.LOCAL_EVIDENCE, + hashValue, + WeIdUtils.getWeIdFromPrivateKey(privateKey), + signature, + log, + String.valueOf(timestamp), + String.valueOf(0), + StringUtils.EMPTY, + groupId); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[createEvidence] save evidence to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(hashValue, ErrorCode.SUCCESS); + } + + @Override + public ResponseData createEvidenceWithCustomKey( + String hashValue, + String signature, + String log, + Long timestamp, + String extraKey, + String privateKey + ) { + if (StringUtils.isEmpty(hashValue) || StringUtils.isEmpty(hashValue) || StringUtils.isEmpty(signature) || StringUtils.isEmpty(privateKey)) { + logger.error("[createEvidenceWithCustomKey] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + if(getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValue).getResult() != null) { + logger.error("[createEvidenceWithCustomKey] evidence with the hash value already existed"); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_ALREADY_EXISTS); + } + + ResponseData resp = + getDataDriver().addEvidenceByHash( + DataDriverConstant.LOCAL_EVIDENCE, + hashValue, + WeIdUtils.getWeIdFromPrivateKey(privateKey), + signature, + log, + String.valueOf(timestamp), + String.valueOf(0), + extraKey, + groupId); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[createEvidenceWithCustomKey] save evidence to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Get the evidence from blockchain. + * + * @param hashValue the evidence hash on chain + * @return The EvidenceInfo + */ + @Override + public ResponseData getInfo(String hashValue) { + if (StringUtils.isEmpty(hashValue)) { + logger.error("[getInfo] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + EvidenceInfo evidenceInfo = new EvidenceInfo(); + evidenceInfo.setCredentialHash(hashValue); + EvidenceValue evidenceValue = getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValue).getResult(); + if(evidenceValue == null){ + logger.error("[getInfo] evidence not exist on chain"); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + Map signInfoMap = new HashMap<>(); + String[] signerList = evidenceValue.getSigners().split(";"); + String[] signatureList = evidenceValue.getSignatures().split(";"); + String[] timestampList = evidenceValue.getUpdated().split(";"); + String[] logList = evidenceValue.getLogs().split(";"); + String[] revokedList = evidenceValue.getRevoked().split(";"); + for(int i = 0; i < signerList.length; i++){ + if(signInfoMap.containsKey(WeIdUtils.convertWeIdToAddress(signerList[i]))){ + EvidenceSignInfo evidenceSignInfo = signInfoMap.get(WeIdUtils.convertWeIdToAddress(signerList[i])); + if(!signatureList[i].equals("empty signature")) evidenceSignInfo.setSignature(signatureList[i]); + evidenceSignInfo.setTimestamp(timestampList[i]); + evidenceSignInfo.setRevoked(revokedList[i].equals("1")); + List logs = evidenceSignInfo.getLogs(); + logs.add(logList[i]); + evidenceSignInfo.setLogs(logs); + signInfoMap.put(WeIdUtils.convertWeIdToAddress(signerList[i]), evidenceSignInfo); + } else { + EvidenceSignInfo evidenceSignInfo = new EvidenceSignInfo(); + if(!signatureList[i].equals("empty signature")) evidenceSignInfo.setSignature(signatureList[i]); + evidenceSignInfo.setTimestamp(timestampList[i]); + evidenceSignInfo.setRevoked(revokedList[i].equals("1")); + List logs = evidenceSignInfo.getLogs(); + logs.add(logList[i]); + evidenceSignInfo.setLogs(logs); + signInfoMap.put(WeIdUtils.convertWeIdToAddress(signerList[i]), evidenceSignInfo); + } + } + evidenceInfo.setSignInfo(signInfoMap); + return new ResponseData<>(evidenceInfo, ErrorCode.SUCCESS); + } + + @Override + public ResponseData> batchCreateEvidence( + List hashValues, + List signatures, + List logs, + List timestamps, + List signers, + String privateKey + ) { + if (hashValues.size() != signatures.size() || hashValues.size() != logs.size() || hashValues.size() != timestamps.size() || hashValues.size() != signers.size()) { + logger.error("[batchCreateEvidence] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + List resultList = new ArrayList<>(); + for(int i = 0; i < hashValues.size(); i++){ + if (StringUtils.isEmpty(hashValues.get(i)) || StringUtils.isEmpty(logs.get(i)) || StringUtils.isEmpty(signatures.get(i)) || StringUtils.isEmpty(signers.get(i))) { + logger.error("[batchCreateEvidence] input argument is illegal"); + resultList.add(false); + continue; + } + if(getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValues.get(i)).getResult() != null) { + logger.error("[batchCreateEvidence] evidence with the hash value already existed"); + resultList.add(false); + continue; + } + ResponseData resp = + getDataDriver().addEvidenceByHash( + DataDriverConstant.LOCAL_EVIDENCE, + hashValues.get(i), + signers.get(i), + signatures.get(i), + logs.get(i), + String.valueOf(timestamps.get(i)), + String.valueOf(0), + StringUtils.EMPTY, + groupId); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[batchCreateEvidence] batch save evidence to db failed."); + resultList.add(false); + continue; + } + resultList.add(true); + } + return new ResponseData<>(resultList, ErrorCode.SUCCESS); + } + + @Override + public ResponseData> batchCreateEvidenceWithCustomKey( + List hashValues, + List signatures, + List logs, + List timestamps, + List signers, + List extraKeys, + String privateKey + ) { + if (hashValues.size() != signatures.size() || hashValues.size() != logs.size() || hashValues.size() != timestamps.size() || hashValues.size() != signers.size() || hashValues.size() != extraKeys.size()) { + logger.error("[batchCreateEvidenceWithCustomKey] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + List resultList = new ArrayList<>(); + for(int i = 0; i < hashValues.size(); i++){ + if (StringUtils.isEmpty(hashValues.get(i)) || StringUtils.isEmpty(logs.get(i)) || StringUtils.isEmpty(signatures.get(i)) || StringUtils.isEmpty(signers.get(i))) { + logger.error("[batchCreateEvidenceWithCustomKey] input argument is illegal"); + resultList.add(false); + continue; + } + if(getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValues.get(i)).getResult() != null) { + logger.error("[batchCreateEvidenceWithCustomKey] evidence with the hash value already existed"); + resultList.add(false); + continue; + } + ResponseData resp = + getDataDriver().addEvidenceByHash( + DataDriverConstant.LOCAL_EVIDENCE, + hashValues.get(i), + signers.get(i), + signatures.get(i), + logs.get(i), + String.valueOf(timestamps.get(i)), + String.valueOf(0), + extraKeys.get(i), + groupId); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[batchCreateEvidenceWithCustomKey] batch save evidence to db failed."); + resultList.add(false); + continue; + } + resultList.add(true); + } + return new ResponseData<>(resultList, ErrorCode.SUCCESS); + } + + @Override + public ResponseData addLog( + String hashValue, + String signature, + String log, + Long timestamp, + String privateKey + ) { + if (StringUtils.isEmpty(hashValue) || StringUtils.isEmpty(log) || StringUtils.isEmpty(privateKey)) { + logger.error("[addLog] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + EvidenceValue evidenceValue = getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValue).getResult(); + if(evidenceValue == null) { + logger.error("[addLog] evidence with the hash value not existed"); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + if(signature.equals(StringUtils.EMPTY)) signature = "empty signature"; + ResponseData resp = + getDataDriver().addSignatureAndLogs( + DataDriverConstant.LOCAL_EVIDENCE, + hashValue, + evidenceValue.getSigners() + ';' + WeIdUtils.getWeIdFromPrivateKey(privateKey), + evidenceValue.getSignatures() + ';' + signature, + evidenceValue.getLogs() + ';' + log, + evidenceValue.getUpdated() + ';' + timestamp, + evidenceValue.getRevoked() + ';' + 0, + evidenceValue.getExtra_key()); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addLog] update evidence to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Get the hash info from blockchain using custom key. + * + * @param customKey the customKey on chain + * @return The EvidenceInfo + */ + @Override + public ResponseData getHashByCustomKey(String customKey) { + if (StringUtils.isEmpty(customKey)) { + logger.error("[getHashByCustomKey] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + EvidenceValue evidenceValue = getDataDriver().getEvidenceByExtraKey(DataDriverConstant.LOCAL_EVIDENCE, customKey).getResult(); + if(evidenceValue == null){ + logger.error("[getHashByCustomKey] evidence not exist on chain"); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + + return new ResponseData<>(evidenceValue.getHash(), ErrorCode.SUCCESS); + } + + @Override + public ResponseData addLogByCustomKey( + String hashValue, + String signature, + String log, + Long timestamp, + String customKey, + String privateKey + ) { + if (StringUtils.isEmpty(hashValue) || StringUtils.isEmpty(log) || StringUtils.isEmpty(privateKey) || StringUtils.isEmpty(customKey)) { + logger.error("[addLogByCustomKey] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + EvidenceValue evidenceValue = getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hashValue).getResult(); + if(evidenceValue == null){ + logger.error("[addLogByCustomKey] evidence not exist on chain"); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + if(signature.equals(StringUtils.EMPTY)) signature = "empty signature"; + ResponseData resp = + getDataDriver().addSignatureAndLogs( + DataDriverConstant.LOCAL_EVIDENCE, + hashValue, + evidenceValue.getSigners() + ';' + WeIdUtils.getWeIdFromPrivateKey(privateKey), + evidenceValue.getSignatures() + ';' + signature, + evidenceValue.getLogs() + ';' + log, + evidenceValue.getUpdated() + ';' + timestamp, + evidenceValue.getRevoked() + ';' + 0, + customKey); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addLogByCustomKey] update evidence to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + + /** + * Get the evidence from blockchain. + * + * @param customKey the evidence hash on chain + * @return The EvidenceInfo + */ + @Override + public ResponseData getInfoByCustomKey(String customKey) { + if (StringUtils.isEmpty(customKey)) { + logger.error("[getInfo] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + EvidenceValue evidenceValue = getDataDriver().getEvidenceByExtraKey(DataDriverConstant.LOCAL_EVIDENCE, customKey).getResult(); + if(evidenceValue == null){ + logger.error("[getInfo] evidence not exist on chain"); + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + return getInfo(evidenceValue.getHash()); + } + + /** + * Revoke an evidence - which can be un-revoked. + * + * @param hash the hash + * @param revokeStage the revokeStage + * @param timestamp the timestamp + * @param privateKey the weid privateKey + * @return true if yes, false otherwise, with error codes + */ + @Override + public ResponseData revoke(String hash, Boolean revokeStage, Long timestamp, String privateKey) { + if (StringUtils.isEmpty(hash) || StringUtils.isEmpty(privateKey)) { + logger.error("[revoke] input argument is illegal"); + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + EvidenceValue evidenceValue = getDataDriver().getEvidenceByHash(DataDriverConstant.LOCAL_EVIDENCE, hash).getResult(); + if(evidenceValue == null) { + logger.error("[revoke] evidence with the hash value not existed"); + return new ResponseData<>(false, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + String[] signerList = evidenceValue.getSigners().split(";"); + String[] revokedList = evidenceValue.getRevoked().split(";"); + String[] timestampList = evidenceValue.getUpdated().split(";"); + String revoked = revokedList[0]; + String timestampStr = timestampList[0]; + for(int i = 0; i < signerList.length; i++){ + if(signerList[i].equals(WeIdUtils.getWeIdFromPrivateKey(privateKey))){ + revokedList[i] = String.valueOf(revokeStage? 1:0); + timestampList[i] = String.valueOf(timestamp); + } + } + String newRevoked = revokedList[0]; + if(revokedList.length != 1) { + for(int i = 1; i < revokedList.length; i++){ + newRevoked = newRevoked + ';' + revokedList[i]; + } + } + String newTimestamp = timestampList[0]; + if(timestampList.length != 1) { + for(int i = 1; i < timestampList.length; i++){ + newTimestamp = newTimestamp + ';' + timestampList[i]; + } + } + ResponseData resp = + getDataDriver().addSignatureAndLogs( + DataDriverConstant.LOCAL_EVIDENCE, + hash, + evidenceValue.getSigners(), + evidenceValue.getSignatures(), + evidenceValue.getLogs(), + newTimestamp, + newRevoked, + evidenceValue.getExtra_key()); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[revoke] update evidence to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + +} diff --git a/src/main/java/com/webank/weid/service/local/PolicyServiceLocal.java b/src/main/java/com/webank/weid/service/local/PolicyServiceLocal.java new file mode 100644 index 00000000..9c5323d2 --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/PolicyServiceLocal.java @@ -0,0 +1,308 @@ +package com.webank.weid.service.local; + +import com.webank.weid.blockchain.constant.ChainType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.constant.WeIdConstant; +import com.webank.weid.blockchain.protocol.base.Cpt; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.PresentationPolicyE; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.blockchain.protocol.response.RsvSignature; +import com.webank.weid.blockchain.rpc.PolicyService; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.protocol.base.GlobalStatus; +import com.webank.weid.suite.persistence.*; +import com.webank.weid.util.PropertyUtils; +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component("policyServiceLocal") +public class PolicyServiceLocal implements PolicyService { + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(PolicyServiceLocal.class); + + private static Persistence dataDriver; + private static PersistenceType persistenceType; + WeIdServiceLocal weIdServiceLocal = new WeIdServiceLocal(); + AuthorityIssuerServiceLocal authorityIssuerServiceLocal = new AuthorityIssuerServiceLocal(); + CptServiceLocal cptServiceLocal = new CptServiceLocal(); + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + /** + * Put Claim Policy List on blockchain under a CPT ID. + * + * @param cptId CPT ID + * @param policies Policy list + * @param privateKey privateKey of cpt issuer + * @return claimPolicyId the Claim policy ID on-chain + */ + @Override + public ResponseData putPolicyIntoCpt(Integer cptId, List policies, + String privateKey) { + if(getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult() == null){ + logger.error("[putPolicyIntoCpt] cpt not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + String policyString = policies.get(0).toString(); + if(policies.size()>1){ + for(int i = 1; i < policies.size(); i++){ + policyString = policyString + "," + policies.get(i).toString(); + } + } + ResponseData resp = + getDataDriver().updateCptClaimPolicies( + DataDriverConstant.LOCAL_CPT, + cptId, + policyString); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[putPolicyIntoCpt] updateCptClaimPolicies to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } + + /** + * Register Claim Policy on blockchain. + * + * @param address address of issuer + * @param cptJsonSchemaNew cptJsonSchema + * @param rsvSignature signature of issuer + * @param privateKey privateKey of issuer + * @return claimPolicyId the Claim policy ID on-chain + */ + @Override + public ResponseData registerPolicyData( + String address, + String cptJsonSchemaNew, + RsvSignature rsvSignature, + String privateKey) { + if (StringUtils.isEmpty(address) || StringUtils.isEmpty(cptJsonSchemaNew) || StringUtils.isEmpty(privateKey)) { + logger.error("[registerPolicyData] input argument is illegal"); + return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); + } + //如果不存在该weId则报错 + if(!weIdServiceLocal.isWeIdExist(WeIdUtils.convertAddressToWeId(address)).getResult()){ + logger.error("[registerPolicyData] the weid of publisher does not exist on blockchain"); + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + int policyId = getPolicyId(address); + + ResponseData resp = + getDataDriver().addPolicy( + DataDriverConstant.LOCAL_POLICY, + policyId, + address, + null, + cptJsonSchemaNew, + com.webank.weid.blockchain.util.DataToolUtils.SigBase64Serialization(rsvSignature)); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerPolicyData] save policy to db failed."); + throw new DatabaseException("database error!"); + } + if (resp.getResult() != null && resp.getResult() > 0) { + return new ResponseData<>(policyId, ErrorCode.SUCCESS); + } else { + return new ResponseData<>(-1, ErrorCode.UNKNOW_ERROR); + } + } + + public int getPolicyId(String address) { + GlobalStatus globalStatus = GlobalStatus.readStatusFromFile("global.status"); + if(authorityIssuerServiceLocal.isAuthorityIssuer(address).getResult()){ + int policyId = globalStatus.getAuthority_issuer_current_policy_id(); + while (getDataDriver().getPolicy(DataDriverConstant.LOCAL_POLICY, policyId).getResult() != null) { + policyId++; + } + globalStatus.setAuthority_issuer_current_policy_id(policyId); + GlobalStatus.storeStatusToFile(globalStatus, "global.status"); + if(policyId > CptServiceLocal.NONE_AUTHORITY_ISSUER_START_ID) policyId = 0; + return policyId; + } else { + int policyId = globalStatus.getNone_authority_issuer_current_policy_id(); + while (getDataDriver().getPolicy(DataDriverConstant.LOCAL_POLICY, policyId).getResult() != null) { + policyId++; + } + globalStatus.setNone_authority_issuer_current_policy_id(policyId); + GlobalStatus.storeStatusToFile(globalStatus, "global.status"); + return policyId; + } + } + + /** + * Get Claim Policy Json from blockchain given a policy ID. + * + * @param policyId the Claim Policy ID on-chain + * @return the claim Json + */ + @Override + public ResponseData getClaimPolicy(Integer policyId) { + try { + PolicyValue policyValue = getDataDriver().getPolicy(DataDriverConstant.LOCAL_POLICY, policyId).getResult(); + if(policyValue == null){ + logger.error("[getClaimPolicy] policy not exist on chain"); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.CPT_NOT_EXISTS); + } + return new ResponseData<>(policyValue.getPolicy_schema(), ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[getClaimPolicy] execute failed. Error message :{}", e); + return new ResponseData<>(StringUtils.EMPTY, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * Get all claim policies from this CPT ID. + * + * @param cptId cpt id + * @return claim policies list + */ + @Override + public ResponseData> getClaimPoliciesFromCpt(Integer cptId) { + CptValue cptValue = getDataDriver().getCpt(DataDriverConstant.LOCAL_CPT, cptId).getResult(); + if(cptValue == null){ + logger.error("[getClaimPoliciesFromCpt] cpt not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + if(cptValue.getClaim_policies() == null){ + return new ResponseData<>(null, ErrorCode.SUCCESS); + } + String[] policies = cptValue.getClaim_policies().split(","); + List result = new ArrayList<>(); + for (String obj : policies) { + result.add(Integer.valueOf(obj)); + } + return new ResponseData<>(result, ErrorCode.SUCCESS); + } + + /** + * Register Presentation Policy which contains a number of claim policies. + * + * @param claimPolicyIdList claim policies list + * @param privateKey privateKey of weid + * @return the presentation policy id + */ + @Override + public ResponseData registerPresentationPolicy(List claimPolicyIdList, + String privateKey) { + int presentationId = getPresentationId(); + String policyString = claimPolicyIdList.get(0).toString(); + if(claimPolicyIdList.size()>1){ + for(int i = 1; i < claimPolicyIdList.size(); i++){ + policyString = policyString + "," + claimPolicyIdList.get(i).toString(); + } + } + ResponseData resp = + getDataDriver().addPresentation( + DataDriverConstant.LOCAL_PRESENTATION, + presentationId, + WeIdUtils.getWeIdFromPrivateKey(privateKey), + policyString); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[registerPresentationPolicy] save presentation to db failed."); + throw new DatabaseException("database error!"); + } + if (resp.getResult() != null && resp.getResult() > 0) { + return new ResponseData<>(resp.getResult(), ErrorCode.SUCCESS); + } else { + return new ResponseData<>(null, ErrorCode.UNKNOW_ERROR); + } + } + + public int getPresentationId() { + GlobalStatus globalStatus = GlobalStatus.readStatusFromFile("global.status"); + int presentationId = globalStatus.getPresentationId(); + while (getDataDriver().getPresentation(DataDriverConstant.LOCAL_PRESENTATION, presentationId).getResult() != null) { + presentationId++; + } + globalStatus.setPresentationId(presentationId); + GlobalStatus.storeStatusToFile(globalStatus, "global.status"); + return presentationId; + } + + /** + * Get Presentation policies under this id from chain. + * + * @param presentationPolicyId presentation policy id + * @return the full presentation policy + */ + @Override + public ResponseData getPresentationPolicy(Integer presentationPolicyId) { + PresentationValue presentationValue = getDataDriver().getPresentation(DataDriverConstant.LOCAL_PRESENTATION, presentationPolicyId).getResult(); + if(presentationValue == null){ + logger.error("[getPresentationPolicy] presentation not exist on chain"); + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + if(presentationValue.getClaim_policies().equals(StringUtils.EMPTY)){ + logger.error("[getPresentationPolicy] presentation does not have policies"); + return new ResponseData<>(null, ErrorCode.POLICY_SERVICE_NOT_EXISTS); + } + String[] policies = presentationValue.getClaim_policies().split(","); + List result = new ArrayList<>(); + for (String obj : policies) { + result.add(Integer.valueOf(obj)); + } + PresentationPolicyE presentationPolicy = new PresentationPolicyE(); + presentationPolicy.setId(presentationValue.getPresentation_id()); + Map policyMap = new HashMap<>(); + for (Integer id : result) { + policyMap.put(id, getClaimPolicy(id).getResult()); + } + presentationPolicy.setPolicy(policyMap); + presentationPolicy.setPolicyPublisherWeId(presentationValue.getCreator()); + return new ResponseData<>(presentationPolicy, ErrorCode.SUCCESS); + } + + /** + * Get all claim policies from chain. + * + * @param startPos start position + * @param num batch number + * @return claim policy list + */ + @Override + public ResponseData> getAllClaimPolicies(Integer startPos, Integer num) { + try { + return getDataDriver().getPolicyIdList( + DataDriverConstant.LOCAL_POLICY, + startPos, + startPos + num); + } catch (Exception e) { + logger.error("[getAllClaimPolicies] getAllClaimPolicies has error, Error Message:{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData getPolicyCount() { + try { + return getDataDriver().getPolicyCount(DataDriverConstant.LOCAL_POLICY); + } catch (Exception e) { + logger.error("[getPolicyCount] getPolicyCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } +} diff --git a/src/main/java/com/webank/weid/service/local/WeIdServiceLocal.java b/src/main/java/com/webank/weid/service/local/WeIdServiceLocal.java new file mode 100644 index 00000000..5f965545 --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/WeIdServiceLocal.java @@ -0,0 +1,257 @@ +package com.webank.weid.service.local; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.blockchain.rpc.WeIdService; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.protocol.base.AuthenticationProperty; +import com.webank.weid.protocol.base.ServiceProperty; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import com.webank.weid.util.WeIdUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + + +@Component("weIdServiceLocal") +public class WeIdServiceLocal implements WeIdService { + + + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(WeIdServiceLocal.class); + private static Persistence dataDriver; + private static PersistenceType persistenceType; + + + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } else if (type.equals("ipfs")) { + persistenceType = PersistenceType.Ipfs; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + /** + * Check if WeIdentity DID exists on Chain. + * + * @param weId the WeIdentity DID + * @return true if exists, false otherwise + */ + @Override + public ResponseData isWeIdExist(String weId) { + try { + ResponseData dbResp = this.getWeIdDocumentMetadata(weId); + if(dbResp.getResult() != null){ + return new ResponseData<>(true, ErrorCode.SUCCESS); + } + return new ResponseData<>(false, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[isWeIdExist] execute failed. Error message :{}", e); + return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + } + } + + /** + * Check if WeIdentity DID is deactivated on Chain. + * + * @param weId the WeIdentity DID + * @return true if is deactivated, false otherwise + */ + @Override + public ResponseData isDeactivated(String weId) { + try { + ResponseData dbResp = this.getWeIdDocumentMetadata(weId); + return new ResponseData<>(dbResp.getResult().isDeactivated(), ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[isDeactivated] execute failed. Error message :{}", e); + return new ResponseData<>(false, ErrorCode.UNKNOW_ERROR); + } + } + + @Override + public ResponseData createWeId( + String address, + List authList, + List serviceList, + String privateKey) { + try { + if(authList.size()==0 || serviceList.size()==0){ + return new ResponseData<>(false, ErrorCode.ILLEGAL_INPUT); + } + String weId = WeIdUtils.convertAddressToWeId(address); + //如果已经存在该weId则报错 + if(this.isWeIdExist(weId).getResult()){ + return new ResponseData<>(false, ErrorCode.WEID_ALREADY_EXIST); + } + //创建weIdDocument插入db + WeIdDocument weIdDocument = new WeIdDocument(); + weIdDocument.setId(weId); + List authenticationList = new ArrayList<>(); + for(String authenticationStr : authList){ + AuthenticationProperty authenticationProperty = AuthenticationProperty.fromString(authenticationStr); + authenticationList.add(authenticationProperty); + } + weIdDocument.setAuthentication(authenticationList); + List serList = new ArrayList<>(); + for(String serviceStr : serviceList){ + ServiceProperty serviceProperty = ServiceProperty.fromString(serviceStr); + serList.add(serviceProperty); + } + weIdDocument.setService(serList); + ResponseData resp = + getDataDriver().addWeId( + DataDriverConstant.LOCAL_WEID_DOCUMENT, + weId, + weIdDocument.toJson()); + if (resp.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error("[createWeId] save weIdDocument to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[createWeId] create weid failed with exception. ", e); + return new ResponseData<>(false, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * Get a WeIdentity DID Document. + * + * @param weId the WeIdentity DID + * @return the WeIdentity DID document + */ + @Override + public ResponseData getWeIdDocument(String weId) { + try { + return getDataDriver().getWeIdDocument( + DataDriverConstant.LOCAL_WEID_DOCUMENT, + weId); + } catch (Exception e) { + logger.error("[getWeIdDocument] execute failed. Error message :{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * Get a WeIdentity DID Document Metadata. + * + * @param weId the WeIdentity DID + * @return the WeIdentity DID document + */ + @Override + public ResponseData getWeIdDocumentMetadata(String weId) { + try { + return getDataDriver().getMeta( + DataDriverConstant.LOCAL_WEID_DOCUMENT, + weId); + } catch (Exception e) { + logger.error("[getWeIdDocumentMetadata] execute failed. Error message :{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /** + * call weid contract to update the weid document. + * + * @param weIdDocument weIdDocument on blockchain + * @param address address of the identity + * @param privateKey privateKey identity's private key + * @return result + */ + @Override + public ResponseData updateWeId( + com.webank.weid.blockchain.protocol.base.WeIdDocument weIdDocument, + String privateKey, + String address) { + try { + String weId = WeIdUtils.getWeIdFromPrivateKey(privateKey); + if(!weId.equals(WeIdUtils.convertAddressToWeId(address))){ + logger.error("[updateWeId] the private key does not match the current weid."); + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + } + ResponseData resp = + getDataDriver().updateWeId( + DataDriverConstant.LOCAL_WEID_DOCUMENT, + weId, + weIdDocument.toJson()); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[updateWeId] updateWeId weIdDocument to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[updateWeId] update weid has error, Error Message:{}", e); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + } + + @Override + public ResponseData> getWeIdList( + Integer first, + Integer last + ) { + try { + return getDataDriver().getWeIdList( + DataDriverConstant.LOCAL_WEID_DOCUMENT, + first, + last); + } catch (Exception e) { + logger.error("[getWeIdList] getWeIdList has error, Error Message:{}", e); + return new ResponseData<>(null, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + @Override + public ResponseData getWeIdCount() { + try { + return getDataDriver().getWeIdCount(DataDriverConstant.LOCAL_WEID_DOCUMENT); + } catch (Exception e) { + logger.error("[getWeIdCount] getWeIdCount has error, Error Message:{}", e); + return new ResponseData<>(0, ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + } + + /*@Override + public ResponseData deactivateWeId( + String weAddress, + String privateKey) { + try { + String weId = WeIdUtils.getWeIdFromPrivateKey(privateKey); + if(!weId.equals(weAddress)){ + logger.error("[updateWeId] the private key does not match the current weid."); + return new ResponseData<>(false, ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH); + } + ResponseData resp = + getDataDriver().deactivateData( + DataDriverConstant.DOMAIN_WEID_DOCUMENT, + weAddress, + true); + if (resp.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error("[deactivateWeId] deactivateWeId failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("[deactivateWeId] deactivate WeId has error, Error Message:{}", e); + return new ResponseData<>(false, ErrorCode.WEID_DOES_NOT_EXIST); + } + }*/ +} diff --git a/src/main/java/com/webank/weid/service/local/role/RoleController.java b/src/main/java/com/webank/weid/service/local/role/RoleController.java new file mode 100644 index 00000000..ec6912f9 --- /dev/null +++ b/src/main/java/com/webank/weid/service/local/role/RoleController.java @@ -0,0 +1,228 @@ +package com.webank.weid.service.local.role; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.service.local.AuthorityIssuerServiceLocal; +import com.webank.weid.service.local.CptServiceLocal; +import com.webank.weid.service.local.WeIdServiceLocal; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.suite.persistence.RoleValue; +import com.webank.weid.util.PropertyUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RoleController { + + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(RoleController.class); + + /** + * Role related Constants. + */ + public static Integer ROLE_AUTHORITY_ISSUER = 100; + public static Integer ROLE_COMMITTEE = 101; + public static Integer ROLE_ADMIN = 102; + + /** + * Operation related Constants. + */ + public static Integer MODIFY_AUTHORITY_ISSUER = 200; + public static Integer MODIFY_COMMITTEE = 201; + public static Integer MODIFY_ADMIN = 202; + public static Integer MODIFY_KEY_CPT = 203; + + private static Persistence dataDriver; + private static PersistenceType persistenceType; + WeIdServiceLocal weIdServiceLocal = new WeIdServiceLocal(); + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + public static Boolean checkPermission(String weId, Integer operation) { + RoleValue result = getDataDriver().getRole(DataDriverConstant.LOCAL_ROLE, weId).getResult(); + if(result == null) { + return false; + } + if(operation == RoleController.MODIFY_AUTHORITY_ISSUER) { + if(result.getAdmin_role() == 1 || result.getCommittee_role() == 1) { + return true; + } + } + if(operation == RoleController.MODIFY_COMMITTEE) { + if(result.getAdmin_role() == 1) { + return true; + } + } + if(operation == RoleController.MODIFY_ADMIN) { + if(result.getAdmin_role() == 1) { + return true; + } + } + if(operation == RoleController.MODIFY_KEY_CPT) { + if(result.getAuthority_role() == 1) { + return true; + } + } + return false; + } + + //operator为操作者,相当于tx.origin, weId为操作对象 + public Boolean addRole(String operator, String weId, Integer role) { + if(role == RoleController.ROLE_AUTHORITY_ISSUER) { + //检查操作者权限 + if(checkPermission(operator, RoleController.MODIFY_AUTHORITY_ISSUER)) { + ResponseData resp = + getDataDriver().addRole( + DataDriverConstant.LOCAL_ROLE, + weId, + 1); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addRole] save role to db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + } + if(role == RoleController.ROLE_COMMITTEE) { + if(checkPermission(operator, RoleController.MODIFY_COMMITTEE)) { + ResponseData resp = + getDataDriver().addRole( + DataDriverConstant.LOCAL_ROLE, + weId, + 2); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addRole] save role to db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + } + if(role == RoleController.ROLE_ADMIN) { + if(checkPermission(operator, RoleController.MODIFY_ADMIN)) { + ResponseData resp = + getDataDriver().addRole( + DataDriverConstant.LOCAL_ROLE, + weId, + 3); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addRole] save role to db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + } + return false; + } + + public Boolean removeRole(String operator, String weId, Integer role) { + RoleValue result = getDataDriver().getRole(DataDriverConstant.LOCAL_ROLE, weId).getResult(); + if(role == RoleController.ROLE_AUTHORITY_ISSUER) { + if(checkPermission(operator, RoleController.MODIFY_AUTHORITY_ISSUER)) { + if(result.getAuthority_role() == 1) { + ResponseData resp = + getDataDriver().updateRole( + DataDriverConstant.LOCAL_ROLE, + weId, + computeRoleValue(result)-1); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeRole] remove role from db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + logger.error("[removeRole] this weId has not authority role."); + return false; + } + } + if(role == RoleController.ROLE_COMMITTEE) { + if(checkPermission(operator, RoleController.MODIFY_COMMITTEE)) { + if(result.getCommittee_role() == 1) { + ResponseData resp = + getDataDriver().updateRole( + DataDriverConstant.LOCAL_ROLE, + weId, + computeRoleValue(result)-2); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeRole] remove role from db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + logger.error("[removeRole] this weId has not committee role."); + return false; + } + } + if(role == RoleController.ROLE_ADMIN) { + if(checkPermission(operator, RoleController.MODIFY_ADMIN)) { + if(result.getAdmin_role() == 1) { + ResponseData resp = + getDataDriver().updateRole( + DataDriverConstant.LOCAL_ROLE, + weId, + computeRoleValue(result)-4); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[removeRole] remove role from db failed."); + throw new DatabaseException("database error!"); + } + return true; + } + logger.error("[removeRole] this weId has not admin role."); + return false; + } + } + return false; + } + + private static int computeRoleValue(RoleValue roleValue) { + if(roleValue.getAuthority_role() == 1){ + if(roleValue.getCommittee_role() == 1){ + if(roleValue.getAdmin_role() == 1){ + return 7; + } + return 3; + }else if(roleValue.getAdmin_role() == 1){ + return 5; + }else {return 1;} + }else if(roleValue.getCommittee_role() == 1){ + if(roleValue.getAdmin_role() == 1){ + return 6; + } + return 2; + }else {return 4;} + } + + public static Boolean checkRole(String weId, Integer role){ + RoleValue result = getDataDriver().getRole(DataDriverConstant.LOCAL_ROLE, weId).getResult(); + if(result == null) { + return false; + } + if(role == RoleController.ROLE_AUTHORITY_ISSUER){ + return result.getAuthority_role() == 1; + } + if(role == RoleController.ROLE_COMMITTEE){ + return result.getCommittee_role() == 1; + } + if(role == RoleController.ROLE_ADMIN){ + return result.getAdmin_role() == 1; + } + logger.error("[checkRole] input role invalid."); + return false; + } + +} diff --git a/src/main/java/com/webank/weid/service/rpc/AuthorityIssuerService.java b/src/main/java/com/webank/weid/service/rpc/AuthorityIssuerService.java new file mode 100644 index 00000000..32f00127 --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/AuthorityIssuerService.java @@ -0,0 +1,197 @@ + + +package com.webank.weid.service.rpc; + +import java.util.List; + +import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.IssuerType; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; +import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Service inf for operations on Authority Issuer. + * + * @author chaoxinhu 2018.10 + */ +public interface AuthorityIssuerService { + + /** + * Register a new Authority Issuer on Chain. + * + *

The input argument actually includes: WeIdentity DID, Name, CreateDate, and Accumulator + * Value. They will be stored into the 3 fields on the chain: the Bytes32 field (Name); the Int + * field (create date); the Dynamic Bytes field (accValue). The data Read and Write sequence is + * fixed in the above mentioned order. + * + * @param args the args + * @return true if succeeds, false otherwise + */ + ResponseData registerAuthorityIssuer(RegisterAuthorityIssuerArgs args); + + /** + * Remove a new Authority Issuer on Chain. + * + * @param args the args + * @return true if succeeds, false otherwise + */ + ResponseData removeAuthorityIssuer(RemoveAuthorityIssuerArgs args); + + /** + * Check whether the given WeIdentity DID is an authority issuer, or not. + * + * @param weId the WeIdentity DID + * @return true if yes, false otherwise + */ + ResponseData isAuthorityIssuer(String weId); + + /** + * Recognize this WeID to be an authority issuer. + * + * @param weId the WeID + * @param weIdPrivateKey the private key set + * @return true if succeeds, false otherwise + */ + ResponseData recognizeAuthorityIssuer(String weId, WeIdPrivateKey weIdPrivateKey); + + /** + * De-recognize this WeID to no longer be and authority issuer. + * + * @param weId the WeID + * @param weIdPrivateKey the private key set + * @return true if succeeds, false otherwise + */ + ResponseData deRecognizeAuthorityIssuer(String weId, WeIdPrivateKey weIdPrivateKey); + + /** + * Query the authority issuer information from a given WeIdentity DID. + * + * @param weId the WeIdentity DID + * @return authority issuer info + */ + ResponseData queryAuthorityIssuerInfo(String weId); + + /** + * Get all of the authority issuer. + * + * @param index start position + * @param num number of returned authority issuer in this request + * @return Execution result + */ + ResponseData> getAllAuthorityIssuerList(Integer index, Integer num); + + /** + * Register a new issuer type. + * + * @param callerAuth the caller + * @param issuerType the specified issuer type + * @return Execution result + */ + ResponseData registerIssuerType(WeIdAuthentication callerAuth, String issuerType); + + /** + * Marked an issuer as the specified issuer type. + * + * @param callerAuth the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param targetIssuerWeId the weId of the issuer who will be marked as a specific issuer type + * @return Execution result + */ + ResponseData addIssuerIntoIssuerType( + WeIdAuthentication callerAuth, + String issuerType, + String targetIssuerWeId + ); + + /** + * Removed an issuer from the specified issuer list. + * + * @param callerAuth the caller who have the access to modify this list + * @param issuerType the specified issuer type + * @param targetIssuerWeId the weId of the issuer to be removed from a specific issuer list + * @return Execution result + */ + ResponseData removeIssuerFromIssuerType( + WeIdAuthentication callerAuth, + String issuerType, + String targetIssuerWeId + ); + + /** + * Check if the given WeId is belonging to a specific issuer type. + * + * @param issuerType the issuer type + * @param targetIssuerWeId the WeId + * @return true if yes, false otherwise + */ + ResponseData isSpecificTypeIssuer( + String issuerType, + String targetIssuerWeId + ); + + /** + * Get all specific typed issuer in a list. + * + * @param issuerType the issuer type + * @param index the start position index + * @param num the number of issuers + * @return the list + */ + ResponseData> getAllSpecificTypeIssuerList( + String issuerType, + Integer index, + Integer num + ); + + /** + * Get an issuer's WeID from its name (org ID). + * + * @param orgId the org id + * @return WeID + */ + ResponseData getWeIdByOrgId(String orgId); + + /** + * get the issuer count. + * @return the all issuer + */ + ResponseData getIssuerCount(); + + /** + * get the issuer count with Recognized. + * @return the all issuer with Recognized + */ + ResponseData getRecognizedIssuerCount(); + + /** + * get the issuer size in issuerType. + * @param issuerType the issuerType + * @return the all issuer in issuerType + */ + ResponseData getSpecificTypeIssuerSize(String issuerType); + + /** + * get the issuer type count. + * @return the all issuer type + */ + ResponseData getIssuerTypeCount(); + + /** + * remove the issuerType. + * @param callerAuth the caller + * @param issuerType the issuerType name + * @return true is success, false is fail + */ + ResponseData removeIssuerType(WeIdAuthentication callerAuth, String issuerType); + + /** + * get the issuerType list. + * @param index the start index + * @param num the page size + * @return the issuerType list + */ + ResponseData> getIssuerTypeList(Integer index, Integer num); +} diff --git a/src/main/java/com/webank/weid/service/rpc/CptService.java b/src/main/java/com/webank/weid/service/rpc/CptService.java new file mode 100644 index 00000000..5661f505 --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/CptService.java @@ -0,0 +1,105 @@ + + +package com.webank.weid.service.rpc; + +import java.util.List; + +import com.webank.wedpr.selectivedisclosure.CredentialTemplateEntity; + +import com.webank.weid.protocol.base.Cpt; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Service inf for operation on CPT (Claim protocol Type). + * + * @author lingfenghe + */ +public interface CptService { + + /** + * Register a new CPT to the blockchain. + * + * @param args the args + * @return The registered CPT info + */ + ResponseData registerCpt(CptMapArgs args); + + /** + * Register a new CPT with a pre-set CPT ID, to the blockchain. + * + * @param args the args + * @param cptId the CPT ID + * @return The registered CPT info + */ + ResponseData registerCpt(CptMapArgs args, Integer cptId); + + /** + * Register a new CPT to the blockchain. + * + * @param args the args + * @return The registered CPT info + */ + ResponseData registerCpt(CptStringArgs args); + + /** + * Register a new CPT with a pre-set CPT ID, to the blockchain. + * + * @param args the args + * @param cptId the CPT ID + * @return The registered CPT info + */ + ResponseData registerCpt(CptStringArgs args, Integer cptId); + + /** + * Query the latest CPT version. + * + * @param cptId the cpt id + * @return The registered CPT info + */ + ResponseData queryCpt(Integer cptId); + + /** + * Update the data fields of a registered CPT. + * + * @param args the args + * @param cptId the cpt id + * @return The updated CPT info + */ + ResponseData updateCpt(CptMapArgs args, Integer cptId); + + /** + * Update the data fields of a registered CPT. + * + * @param args the args + * @param cptId the cpt id + * @return The updated CPT info + */ + ResponseData updateCpt(CptStringArgs args, Integer cptId); + + /** + * Update the data fields of a registered CPT. + * + * @param cptId the cpt id + * @return The updated CPT info + */ + ResponseData queryCredentialTemplate(Integer cptId); + + /** + * Get CPTIDS from chain. + * + * @param startPos start position + * @param num batch number + * @return CPTID list + */ + ResponseData> getCptIdList(Integer startPos, Integer num); + + /** + * Get CPT count. + * + * @return the cpt count + */ + ResponseData getCptCount(); +} diff --git a/src/main/java/com/webank/weid/service/rpc/CredentialPojoService.java b/src/main/java/com/webank/weid/service/rpc/CredentialPojoService.java new file mode 100644 index 00000000..11bb928e --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/CredentialPojoService.java @@ -0,0 +1,210 @@ + +package com.webank.weid.service.rpc; + +import com.networknt.schema.ValidationMessage; +import com.webank.weid.protocol.base.Challenge; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.Cpt; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.PresentationE; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.cpt.Cpt101; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import java.util.List; +import java.util.Set; + +/** + * Service inf for operations on Credentials. + * + * @author tonychen + */ +public interface CredentialPojoService { + + /** + * Generate a credential for full claim content. + * + * @param args the args + * @return CredentialPojo + */ + ResponseData createCredential(CreateCredentialPojoArgs args); + + /** + * user make credential from issuer's pre-credential. + * + * @param preCredential issuer's pre-credential + * @param claimJson user claim + * @param weIdAuthentication auth + * @return credential based on CPT 111 + */ + ResponseData prepareZkpCredential( + CredentialPojo preCredential, + String claimJson, + WeIdAuthentication weIdAuthentication + ); + + /** + * Generate a selective disclosure credential with specified claim policy. + * + * @param credential the credential + * @param claimPolicy describe which fields in credential should be disclosed. + * @return CredentialPojo + */ + ResponseData createSelectiveCredential( + CredentialPojo credential, + ClaimPolicy claimPolicy + ); + + /** + * Add an extra signer and signature to a Credential. Multiple signatures will be appended in an + * embedded manner. + * + * @param credentialList original credential list + * @param callerAuth the passed-in privateKey and WeID bundle to sign + * @return the modified CredentialWrapper + */ + ResponseData addSignature( + List credentialList, + WeIdAuthentication callerAuth + ); + + /** + * Get the full hash value of a CredentialPojo. All fields in the CredentialPojo will be + * included. This method should be called when creating and verifying the Credential Evidence + * and the result is selectively-disclosure irrelevant. + * + * @param credentialPojo the args + * @return the Credential Hash value + */ + ResponseData getCredentialPojoHash(CredentialPojo credentialPojo); + + /** + * Verify the validity of a credential. Public key will be fetched from chain. + * + * @param issuerWeId the issuer WeID + * @param credential the credential + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verify(String issuerWeId, CredentialPojo credential); + + /** + * Verify the validity of a credential with public key fetched from chain. Here you can specify + * the public key ID from the WeID Document if you well know the ID (you can pass the whole + * string, or just the ID). + * + * @param issuerWeId the issuer WeID + * @param weIdPublicKeyId the public key + * @param credential the credential + * @return true if succeeded, false otherwise + */ + ResponseData verify( + String issuerWeId, + String weIdPublicKeyId, + CredentialPojo credential + ); + + /** + * Verify the validity of a credential. Public key must be provided. + * + * @param issuerPublicKey the specified public key which used to verify credential signature + * @param credential the credential + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verify(WeIdPublicKey issuerPublicKey, CredentialPojo credential); + + /** + * verify the presentation with presenter's weid and policy. + * + * @param presenterWeId the presenter's weid + * @param presentationPolicyE policy of the presentation + * @param challenge challenge + * @param presentationE the presentation + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verify( + String presenterWeId, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + PresentationE presentationE + ); + + /** + * Verify the validity of a credential. Public key must be provided. This is offline interface. + * + * @param issuerPublicKey the specified public key which used to verify credential signature + * @param credential the credential + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verifyOffline(WeIdPublicKey issuerPublicKey, CredentialPojo credential); + + /** + * verify the presentation and pdf information. + * @param pdfTemplatePath path of pdf template + * @param serializePdf byte[] of serialize by pdf transportation + * @param presenterWeId the presenter's weid + * @param presentationPolicyE policy of the presentation + * @param challenge challenge + * @param presentationE the presentation + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + /*ResponseData verifyPresentationFromPdf( + String pdfTemplatePath, + byte[] serializePdf, + String presenterWeId, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + PresentationE presentationE + ); +*/ + /** + * packing according to original vouchers and disclosure strategies. + * + * @param credentialList original credential list + * @param presentationPolicyE the disclosure strategies. + * @param challenge used for authentication + * @param weIdAuthentication owner information + * @return PresentationE presentationE + */ + ResponseData createPresentation( + List credentialList, + PresentationPolicyE presentationPolicyE, + Challenge challenge, + WeIdAuthentication weIdAuthentication + ); + + /** + * Create a trusted timestamp credential. + * + * @param credentialList the credentialPojo list to be signed + * @param weIdAuthentication caller authentication + * @return the embedded timestamp in credentialPojo + */ + ResponseData createTrustedTimestamp( + List credentialList, + WeIdAuthentication weIdAuthentication + ); + + /** + * Create a data authorization token. + * + * @param authInfo the authorization info in CPT101 format + * @param weIdAuthentication the caller (authorization issuer) authentication + * @return the data authorization token in credentialPojo + */ + ResponseData createDataAuthToken( + Cpt101 authInfo, + WeIdAuthentication weIdAuthentication + ); + + /** + * Check the credential with CPT. + * + * @param credential the CredentialPojo + * @param cpt the CPT information + * @return return ProcessingReport + */ + ResponseData> checkCredentialWithCpt(CredentialPojo credential, Cpt cpt); +} + diff --git a/src/main/java/com/webank/weid/service/rpc/CredentialService.java b/src/main/java/com/webank/weid/service/rpc/CredentialService.java new file mode 100644 index 00000000..82c19463 --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/CredentialService.java @@ -0,0 +1,118 @@ + + +package com.webank.weid.service.rpc; + +import java.util.List; + +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialWrapper; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.CreateCredentialArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Service inf for operations on Credentials. + * + * @author chaoxinhu 2018.12 + */ +public interface CredentialService { + + /** + * Generate a credential for full claim content. + * + * @param args the args + * @return credential wrapper + */ + ResponseData createCredential(CreateCredentialArgs args); + + /** + * WARNING: To be deprecated in near future. We strongly suggest to use CredentialPojo for + * multi-signature purpose. This can add an extra signer and signature to a Credential. Multiple + * signatures will be appended in an embedded manner. + * + * @param credentialList original credential + * @param weIdPrivateKey the passed-in privateKey to add sign + * @return the modified CredentialWrapper + */ + @Deprecated + ResponseData addSignature( + List credentialList, + WeIdPrivateKey weIdPrivateKey + ); + + /** + * Generate a credential with selected data. Embedded multi-signed Credential are not allowed. + * + * @param credential the credential + * @param disclosure the setting of disclosure, such as: {@code{"name":1,"gender":0,"age":1}}, + * which means you WILL disclose "name" and "age", and "gender" WILL NOT be disclosed + * @return CredentialWrapper + */ + ResponseData createSelectiveCredential( + Credential credential, + String disclosure + ); + + /** + * Verify the validity of a credential. Public key will be fetched from chain. If the credential + * is multi-signed, it will verify each signature in an embedded manner. + * + * @param credential the credential + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verify(Credential credential); + + /** + * Verify the validity of a credential. Public key will be fetched from chain. If the credential + * * is multi-signed, it will verify each signature in an embedded manner. + * + * @param credentialWrapper the credentialWrapper + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verify(CredentialWrapper credentialWrapper); + + /** + * Verify the validity of a credential. Public key must be provided. Embedded multi-signed + * Credential are not allowed. + * + * @param credentialWrapper the credential wrapper + * @param weIdPublicKey the specified public key which used to verify credential signature + * @return the verification result. True if yes, false otherwise with exact verify error codes + */ + ResponseData verifyCredentialWithSpecifiedPubKey( + CredentialWrapper credentialWrapper, + WeIdPublicKey weIdPublicKey + ); + + /** + * Get the full hash value of a Credential. All fields in the Credential will be included. This + * method should be called when creating and verifying the Credential Evidence. + * + * @param credential the args + * @return the Credential Hash value + */ + ResponseData getCredentialHash(Credential credential); + + /** + * Get the full hash value of a Credential with its selectively-disclosure map. All fields in + * the Credential will be included. This method should be called when creating and verifying the + * Credential Evidence and the result is selectively-disclosure irrelevant. + * + * @param credential the args + * @return the Credential Hash value + */ + ResponseData getCredentialHash(CredentialWrapper credential); + + /** + * WARNING: To be deprecated in near future - use DataToolUtils.serialize() instead! Get the + * Json String of a Credential. All fields in the Credential will be included. This also + * supports the selectively disclosed Credential. + * + * @param credential the credential + * @return the Credential Json value in String + */ + @Deprecated + ResponseData getCredentialJson(Credential credential); + +} diff --git a/src/main/java/com/webank/weid/service/rpc/EvidenceService.java b/src/main/java/com/webank/weid/service/rpc/EvidenceService.java new file mode 100644 index 00000000..16c04b5b --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/EvidenceService.java @@ -0,0 +1,259 @@ + + +package com.webank.weid.service.rpc; + +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.EvidenceInfo; +import com.webank.weid.protocol.base.HashString; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.inf.Hashable; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Service inf for operations on Evidence for Credentials. + * + * @author chaoxinhu 2019.1 + */ +public interface EvidenceService { + + /** + * Create a new evidence to blockchain, and return the evidence's hash value on-chain. Supports + * following types of input: Credential, CredentialWrapper, CredentialPojo, plain hash String, + * After a successful creation, the hash value will be recorded onto blockchain, and this hash + * value can be used as key to lookup on blockchain. This will fail if evidence already exists. + * + * @param object the given Java object + * @param weIdPrivateKey the signer WeID's private key + * @return evidence hash value. Return empty string if failed, e.g. already existed. + */ + ResponseData createEvidence(Hashable object, WeIdPrivateKey weIdPrivateKey); + + /** + * Create a new evidence to blockchain and return the hash value, with appending log. This will + * fail if evidence already exists. + * + * @param object the given Java object + * @param log appendable log entry - can be null or empty + * @param weIdAuthentication weid authentication (only checks private key) + * @return evidence hash value. Return empty string if failed, e.g. already existed. + */ + ResponseData createEvidenceWithLog( + Hashable object, + String log, + WeIdAuthentication weIdAuthentication + ); + + /** + * Create a new evidence together with log and custom key. Other guys can use this custom key, + * OR its hash value, to lookup the detailed information of this evidence. Multiple calls of + * this method will yield multiple log entries as the same of addLog(). + * + * @param object the given Java object + * @param weIdPrivateKey the signer WeID's private key + * @param log appendable log entry - can be null or empty + * @param customKey custom key determined by creator - it cannot be a hash value though + * @return evidence hash value + */ + ResponseData createEvidenceWithLogAndCustomKey( + Hashable object, + WeIdPrivateKey weIdPrivateKey, + String log, + String customKey + ); + + /** + * Add log entry for an existing evidence, appending on existing log entries. This log will be + * recorded on blockchain permanently, and finally it will be fetched as a list when trying to + * get evidence. Log must not be empty. + * + * @param hashValue hash value + * @param log Not null log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + ResponseData addLogByHash( + String hashValue, + String log, + WeIdPrivateKey weIdPrivateKey + ); + + /** + * Add signature and log as a new signer to an existing evidence, appending on existing log + * entries. Log must not be empty. The signer might be different than the existing signers. + * + * @param hashValue hash value + * @param log Not null log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + ResponseData addSignatureAndLogByHash( + String hashValue, + String log, + WeIdPrivateKey weIdPrivateKey + ); + + /** + * Add log entry for an existing evidence, appending on existing log entries. This log will be + * recorded on blockchain permanently, and finally it will be fetched as a list when trying to + * get evidence. Log must not be empty. It will firstly try to fetch the hash value given the + * custom key, and if the hash value does not exist, it will use the supplementing hash value + * (1st parameter) to make up. + * + * @param hashValueSupplement the hash value supplement if the custom key does not exist + * @param customKey custom key + * @param log Not null log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + ResponseData addLogByCustomKey( + String hashValueSupplement, + String customKey, + String log, + WeIdPrivateKey weIdPrivateKey + ); + + /** + * Add signature and log as a new signer to an existing evidence. Log can be empty. + * + * @param hashValueSupplement the hash value supplement if the custom key does not exist + * @param customKey custom key + * @param log Not null log entry + * @param weIdPrivateKey the signer WeID's private key + * @return true if succeeded, false otherwise + */ + ResponseData addSignatureAndLogByCustomKey( + String hashValueSupplement, + String customKey, + String log, + WeIdPrivateKey weIdPrivateKey + ); + + /** + * Revoke an evidence - which can be un-revoked. + * + * @param object the object + * @param weIdAuthentication the weid authentication + * @return true if yes, false otherwise, with error codes + */ + ResponseData revoke(Hashable object, WeIdAuthentication weIdAuthentication); + + /** + * Un-revoke an evidence. + * + * @param object the object + * @param weIdAuthentication the weid authentication + * @return true if yes, false otherwise, with error codes + */ + ResponseData unRevoke(Hashable object, WeIdAuthentication weIdAuthentication); + + /** + * Check whether this evidence is revoked by this WeID. + * + * @param evidenceInfo the EvidenceInfo + * @param weId the signer WeID + * @return true if revoked, false otherwise + */ + ResponseData isRevoked(EvidenceInfo evidenceInfo, String weId); + + /** + * Get the evidence info from blockchain using hash as key. + * + * @param hashValue the hash, on chain + * @return The EvidenceInfo + */ + ResponseData getEvidence(String hashValue); + + /** + * Get the evidence info from blockchain using custom key. + * + * @param customKey the custom key, on chain + * @return The EvidenceInfo + */ + ResponseData getEvidenceByCustomKey(String customKey); + + /** + * Generate hash value of any passed-in param. + * + * @param object param to be hashed + * @param type of param + * @return the hash string + */ + ResponseData generateHash(T object); + + /** + * Validate whether a credential created the evidence, and this evidence is signed by this WeID + * - will perform on-Chain key check. + * + * @param credentialPojo the credentialPojo + * @param evidenceInfo the evidence info fetched from chain + * @param weId the WeID + * @return true if yes, false otherwise + */ + ResponseData verifySigner( + CredentialPojo credentialPojo, + EvidenceInfo evidenceInfo, + String weId + ); + + /** + * Validate whether a credential created the evidence, and this evidence is signed by this WeID + * based on the passed-in publicKey. + * + * @param credentialPojo the credentialPojo + * @param evidenceInfo the evidence info fetched from chain + * @param weId the WeID + * @param publicKey the public key + * @return true if yes, false otherwise + */ + ResponseData verifySigner( + CredentialPojo credentialPojo, + EvidenceInfo evidenceInfo, + String weId, + String publicKey + ); + + /** + * A direct pass-thru method to create raw evidence where all inputs can be customized. + * + * @param hashValue the hash value + * @param signature the signature value + * @param log the log + * @param timestamp the timestamp + * @param extraKey the extra data + * @param privateKey the private key + * @return true if yes, false otherwise + */ + @Deprecated + ResponseData createRawEvidenceWithCustomKey( + String hashValue, + String signature, + String log, + Long timestamp, + String extraKey, + String privateKey + ); + + /** + * A direct pass-thru method to create raw evidence where all inputs, including signer, can be + * customized. + * + * @param hashValue the hash value + * @param signature the signature value + * @param log the log + * @param timestamp the timestamp + * @param extraKey the extra data + * @param signer the signer + * @param privateKey the private key + * @return true if yes, false otherwise + */ + ResponseData createRawEvidenceWithSpecificSigner( + String hashValue, + String signature, + String log, + Long timestamp, + String extraKey, + String signer, + String privateKey + ); +} diff --git a/src/main/java/com/webank/weid/service/rpc/PolicyService.java b/src/main/java/com/webank/weid/service/rpc/PolicyService.java new file mode 100644 index 00000000..437133ae --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/PolicyService.java @@ -0,0 +1,79 @@ + + +package com.webank.weid.service.rpc; + +import java.util.List; + +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Service inf for operation on Policy on blockchain (Claim protocol Type). + * + * @author junqizhang 2020.8 + */ +public interface PolicyService { + + /** + * Register Claim Policy on blockchain and assign it under a CPT ID. + * + * @param cptId CPT ID + * @param policyJson Policy Json file + * @param weIdAuthentication WeID auth + * @return claimPolicyId the Claim policy ID on-chain + */ + ResponseData registerClaimPolicy(Integer cptId, String policyJson, + WeIdAuthentication weIdAuthentication); + + /** + * Get Claim Policy Json from blockchain given a policy ID. + * + * @param policyId the Claim Policy ID on-chain + * @return the claim Json + */ + ResponseData getClaimPolicy(Integer policyId); + + /** + * Get all claim policies from this CPT ID. + * + * @param cptId cpt id + * @return claim policies list + */ + ResponseData> getClaimPoliciesFromCpt(Integer cptId); + + /** + * Register Presentation Policy which contains a number of claim policies. + * + * @param claimPolicyIdList claim policies list + * @param weIdAuthentication weid auth + * @return the presentation policy id + */ + ResponseData registerPresentationPolicy(List claimPolicyIdList, + WeIdAuthentication weIdAuthentication); + + /** + * Get Presentation policies under this id from chain. + * + * @param presentationPolicyId presentation policy id + * @return the full presentation policy + */ + ResponseData getPresentationPolicy(Integer presentationPolicyId); + + /** + * Get all claim policies from chain. + * + * @param startPos start position + * @param num batch number + * @return claim policy list + */ + ResponseData> getAllClaimPolicies(Integer startPos, Integer num); + + /** + * Get Policy count. + * + * @return the Policy count + */ + ResponseData getPolicyCount(); +} diff --git a/src/main/java/com/webank/weid/service/rpc/WeIdService.java b/src/main/java/com/webank/weid/service/rpc/WeIdService.java new file mode 100644 index 00000000..7bd1fdf0 --- /dev/null +++ b/src/main/java/com/webank/weid/service/rpc/WeIdService.java @@ -0,0 +1,151 @@ + + +package com.webank.weid.service.rpc; + +import java.util.List; + +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.CreateWeIdArgs; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.protocol.response.WeIdListResult; + + + +/** + * Service inf for operations on WeIdentity DID. + * + * @author tonychen + */ +public interface WeIdService { + + /** + * Create a WeIdentity DID without a keypair. SDK will generate a keypair for the caller. + * + * @return a data set including a WeIdentity DID and a keypair + */ + ResponseData createWeId(); + + /** + * Create a WeIdentity DID from the provided public key. + * A private key is required to send transaction, but may be not matching the given public key + * + * @param weIdPublicKey you need to input a public key + * @param weIdPrivateKey you need to input a private key + * @return a data set including a WeIdentity DID and a keypair + */ + ResponseData createWeIdByPublicKey(WeIdPublicKey weIdPublicKey, WeIdPrivateKey weIdPrivateKey); + + /** + * Create a WeIdentity DID from the provided public key. + * + *@param createWeIdArgs the create WeIdentity DID args + * @return WeIdentity DID + */ + ResponseData createWeId(CreateWeIdArgs createWeIdArgs); + + /** + * Query WeIdentity DID document. + * + * @param weId the WeIdentity DID + * @return WeIdentity document in json type + */ + ResponseData getWeIdDocumentJson(String weId); + + /** + * Query WeIdentity DID document. + * + * @param weId the WeIdentity DID + * @return weId document in java object type + */ + ResponseData getWeIdDocument(String weId); + + /** + * Query WeIdentity DID document metadata. + * + * @param weId the WeIdentity DID + * @return weId document metadata in java object type + */ + ResponseData getWeIdDocumentMetadata(String weId); + + /** + * Set service properties. + * + * @param weId the WeID to set service to + * @param serviceArgs your service name and endpoint + * @param privateKey the private key + * @return true if the "set" operation succeeds, false otherwise. + */ + ResponseData setService(String weId, ServiceArgs serviceArgs, + WeIdPrivateKey privateKey); + + /** + * Set authentications in WeIdentity DID. + * + * @param weId the WeID to set auth to + * @param authenticationArgs A public key is needed + * @param privateKey the private key + * @return true if the "set" operation succeeds, false otherwise. + */ + ResponseData setAuthentication( + String weId, + AuthenticationArgs authenticationArgs, + WeIdPrivateKey privateKey); + + /** + * Check if the WeIdentity DID exists on chain. + * + * @param weId The WeIdentity DID. + * @return true if exists, false otherwise. + */ + ResponseData isWeIdExist(String weId); + + /** + * Check if the WeIdentity DID is deactivated on chain. + * + * @param weId The WeIdentity DID. + * @return true if is deactivated, false otherwise. + */ + ResponseData isDeactivated(String weId); + + /** + * Remove an authentication tag in WeID document only - will not affect its public key. + * + * @param weId the WeID to remove auth from + * @param authenticationArgs A public key is needed + * @param privateKey the private key + * @return true if succeeds, false otherwise + */ + ResponseData revokeAuthentication( + String weId, + AuthenticationArgs authenticationArgs, + WeIdPrivateKey privateKey); + + /** + * query data according to block height, index location and search direction. + * + * @param first the first index of weid in contract + * @param last the last index of weid in contract + * @return return the WeId List + */ + ResponseData> getWeIdList( + Integer first, + Integer last + ); + + /** + * get total weId. + * + * @return total weid + */ + ResponseData getWeIdCount(); + + /** + * get WeID list by pubKey list. + * @param pubKeyList the pubKey list + * @return return the WeIDListResult + */ + ResponseData getWeIdListByPubKeyList(List pubKeyList); +} diff --git a/src/main/java/com/webank/weid/suite/cache/CacheManager.java b/src/main/java/com/webank/weid/suite/cache/CacheManager.java new file mode 100644 index 00000000..59999f27 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/cache/CacheManager.java @@ -0,0 +1,109 @@ + + +package com.webank.weid.suite.cache; + +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.util.PropertyUtils; + + +/** + * 缓存管理器. + * @author v_wbgyang + * + */ +public class CacheManager { + + //全局缓存上下文 + private static final ConcurrentHashMap> context = + new ConcurrentHashMap>(); + + //默认缓存个数 + private static final Integer MAX_SIZE = 1000; + private static final String CACHE_MAXSIZE_KEY = "caffeineCache.maximumSize."; + + /** + * 根据缓存名获取缓存节点最大缓存个数,如果没有配置则使用默认大小配置. + * @param cacheName 缓存名 + * @return + */ + private static Integer getMaxSize(String cacheName) { + String maximumSize = PropertyUtils.getProperty(CACHE_MAXSIZE_KEY + cacheName); + if (StringUtils.isNotBlank(maximumSize)) { + return Integer.parseInt(maximumSize); + } + return MAX_SIZE; + } + + /** + * 注册缓存节点,如果存在则直接返回,不存在则注册. + * @param 需要存放的数据类型 + * @param cacheName 缓存名 + * @param timeout 超时时间 + * @return 返回缓存节点 + */ + public static CacheNode registerCacheNode(String cacheName, Long timeout) { + return registerCacheNode(cacheName, timeout, getMaxSize(cacheName)); + } + + /** + * 注册缓存节点,如果存在则直接返回,不存在则注册. + * @param 需要存放的数据类型 + * @param cacheName 缓存名 + * @param timeout 超时时间 + * @param maximumSize 最大缓存大小 + * @return 返回缓存节点 + */ + public static CacheNode registerCacheNode( + String cacheName, + Long timeout, + Integer maximumSize) { + + CacheNode cacheNode = context.get(cacheName); + if (cacheNode != null) { + throw new WeIdBaseException("the cacheName is registed, cacheName= " + cacheName); + } + cacheNode = initCache(cacheName, timeout, maximumSize); + CacheNode node = (CacheNode)cacheNode; + return node; + } + + /** + * 失效缓存数据. + */ + public static void clearAll() { + Set>> entrySet = context.entrySet(); + for (Entry> entry : entrySet) { + entry.getValue().removeAll(); + } + } + + /** + * 根据缓存名和超时时间初始化缓存模块. + * @param cacheName 缓存名 + * @param timeout 超时时间 + * @param maximumSize 缓存项大小 + * @return 返回缓存节点对象 + */ + private static synchronized CacheNode initCache( + String cacheName, + Long timeout, + Integer maximumSize) { + + Cache cache = Caffeine.newBuilder() + .expireAfterWrite(timeout, TimeUnit.MILLISECONDS) + .maximumSize(maximumSize) + .build(); + CacheNode node = new CacheNode<>(cacheName, cache); + context.put(cacheName, node); + return node; + } +} diff --git a/src/main/java/com/webank/weid/suite/cache/CacheNode.java b/src/main/java/com/webank/weid/suite/cache/CacheNode.java new file mode 100644 index 00000000..c0227559 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/cache/CacheNode.java @@ -0,0 +1,43 @@ + + +package com.webank.weid.suite.cache; + +import com.github.benmanes.caffeine.cache.Cache; + +/** + * 缓存节点. + * @author v_wbgyang + * + * @param 节点存放的对象泛型 + */ +public class CacheNode { + + private Cache cache; + + private String cacheName; + + CacheNode(String cacheName, Cache cache) { + this.cacheName = cacheName; + this.cache = cache; + } + + public void put(String key, T t) { + cache.put(key, t); + } + + public T get(String key) { + return cache.getIfPresent(key); + } + + public void remove(String key) { + cache.invalidate(key); + } + + public void removeAll() { + cache.invalidateAll(); + } + + public String getCacheName() { + return cacheName; + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/AuthorityIssuerInfo.java b/src/main/java/com/webank/weid/suite/persistence/AuthorityIssuerInfo.java new file mode 100644 index 00000000..52f5c5c0 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/AuthorityIssuerInfo.java @@ -0,0 +1,53 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class AuthorityIssuerInfo { + /** + * 主键,weid. + */ + private String weid; + + /** + * m名字 + */ + private String name; + + /** + * 描述. + */ + private String description; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * 是否已经被确认. + */ + private int recognize; + + /** + * acc_value. + */ + private String acc_value; + + /** + * 附属描述. + */ + private String extra_str; + + /** + * 附属描述. + */ + private String extra_int; +} diff --git a/src/main/java/com/webank/weid/suite/persistence/BaseDomain.java b/src/main/java/com/webank/weid/suite/persistence/BaseDomain.java new file mode 100644 index 00000000..c03fced3 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/BaseDomain.java @@ -0,0 +1,88 @@ + + +package com.webank.weid.suite.persistence; + +import java.util.Date; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.util.PropertyUtils; + +/** + * Persistence通用domain类. + * + * @author karenli + */ + +@Getter +public class BaseDomain { + + /** + * the split for value. + */ + public static final String VALUE_SPLIT_CHAR = ":"; + + /** + * default table name. + */ + public static final String DEFAULT_TABLE = "default_info"; + + /** + * the domain key. + */ + public String key; + + /** + * the domain value. + */ + public String value; + + /** + * the database domain. + */ + public String baseDomain; + + /** + * the table domain. + */ + public String tableDomain; + + /** + * the domain timeout. + */ + public long timeout = 86400000L; + + /** + * resolve Domain Timeout. + * + */ + public void resolveDomainTimeout() { + String timeout = PropertyUtils.getProperty(this.key + ".timeout"); + if (StringUtils.isBlank(timeout)) { + timeout = PropertyUtils.getProperty(DataDriverConstant.DOMAIN_DEFAULT_INFO_TIMEOUT); + } + if (StringUtils.isNotBlank(timeout)) { + this.timeout = Long.parseLong(timeout); + } + } + + /** + * get the expire time. + * + * @return date + */ + public Date getExpire() { + return new Date(System.currentTimeMillis() + this.timeout); + } + + /** + * get the current time. + * + * @return now + */ + public Date getNow() { + return new Date(); + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/CptValue.java b/src/main/java/com/webank/weid/suite/persistence/CptValue.java new file mode 100644 index 00000000..5f5fc14e --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/CptValue.java @@ -0,0 +1,63 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class CptValue { + /** + * 主键,cptId. + */ + private int cpt_id; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * 数据版本. + */ + private int cpt_version; + + /** + * cpt创建者. + */ + private String publisher; + + /** + * cpt描述. + */ + private String description; + + /** + * cpt对象的json序列化. + */ + private String cpt_schema; + + /** + * cpt签名 + */ + private String cpt_signature; + + /** + * credential验证公钥 + */ + private String credential_publicKey; + + /** + * credential证明 + */ + private String credential_proof; + /** + * claim policies列表 + */ + private String claim_policies; + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/DefaultValue.java b/src/main/java/com/webank/weid/suite/persistence/DefaultValue.java new file mode 100644 index 00000000..3e0a036e --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/DefaultValue.java @@ -0,0 +1,67 @@ + + +package com.webank.weid.suite.persistence; + +import java.io.Serializable; +import java.util.Date; + +import lombok.Data; + +@Data +public class DefaultValue { + + /** + * 主键. + */ + private String id; + + /** + * blob主体数据. + */ + private String data; + + /** + * 创建时间. + */ + private Date created; + /** + * 更新时间. + */ + private Date updated; + + /** + * 编码格式. + */ + private String protocol; + + /** + * 超时时间. + */ + private Date expire; + + /** + * 数据所属版本. + */ + private String version; + + /** + * 扩展字段1. + */ + private int ext1; + + /** + * 扩展字段2. + */ + private int ext2; + + /** + * 扩展字段3. + */ + private String ext3; + + /** + * 扩展字段4. + */ + private String ext4; + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/EvidenceValue.java b/src/main/java/com/webank/weid/suite/persistence/EvidenceValue.java new file mode 100644 index 00000000..b27a0ab9 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/EvidenceValue.java @@ -0,0 +1,54 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class EvidenceValue { + /** + * 主键,hash. + */ + private String hash; + + /** + * signers of evidence. + */ + private String signers; + + /** + * signatures of evidence. + */ + private String signatures; + + /** + * logs of evidence. + */ + private String logs; + + /** + * 每个签名的时间. + */ + private String updated; + + /** + * revoke of each signature. + */ + private String revoked; + + /** + * extraKey of evidence. + */ + private String extra_key; + + /** + * extraData of evidence. + */ + private String extra_data; + + /** + * groupId of evidence. + */ + private String group_id; + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/Persistence.java b/src/main/java/com/webank/weid/suite/persistence/Persistence.java new file mode 100644 index 00000000..ba76fb50 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/Persistence.java @@ -0,0 +1,469 @@ + + +package com.webank.weid.suite.persistence; + +import java.util.List; +import java.util.Map; + +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.WeIdDocument; +import com.webank.weid.blockchain.protocol.base.WeIdDocumentMetadata; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Data access driver. + * + * @author tonychen 2019年3月18日 + */ +public interface Persistence { + + /** + * add data to storage. + * + * @param domain the domain of the data. + * @param id the key of the data. + * @param data which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData add(String domain, String id, String data); + + /** + * batch add data to storage. + * + * @param domain the domain of the data. + * @param keyValueList list of id-data. + * @return execute status of the "add" operation. + */ + public ResponseData batchAdd(String domain, Map keyValueList); + + /** + * query data from storage by id. + * + * @param domain the domain of the data. + * @param id the key of the data. + * @return the data you stored. + */ + public ResponseData get(String domain, String id); + + /** + * delete data by id. + * + * @param domain the domain of the data. + * @param id the key of the data. + * @return the data you stored. + */ + public ResponseData delete(String domain, String id); + + /** + * update data by id. + * + * @param domain the domain of the data. + * @param id the key you store with. + * @param data the data you want to update into. + * @return execute status of the "update" operation. + */ + public ResponseData update(String domain, String id, String data); + + /** + * add data to storage if not exist, others for update. + * + * @param domain the domain of the data. + * @param id the key of the data. + * @param data which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData addOrUpdate(String domain, String id, String data); + + /** + * add transaction to storage. + * + * @param transactionArgs the transaction info. + * @return execute status of the "addTransaction" operation. + */ + public ResponseData addTransaction(TransactionArgs transactionArgs); + /** + * add data to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param documentSchema which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData addWeId(String domain, String weId, String documentSchema); + /** + * add data to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param documentSchema which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData updateWeId(String domain, String weId, String documentSchema); + /** + * query WeIdDocumentMetadata from storage by id. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @return the data you stored. + */ + public ResponseData getWeIdDocument(String domain, String weId); + /** + * query WeIdDocumentMetadata from storage by id. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @return the data you stored. + */ + public ResponseData getMeta(String domain, String weId); + + /** + * deactivateWeId by id. + * + * @param domain the domain of the data. + * @param weId the weId you want to deactivate. + * @param state the state you want to change. + * @return execute status of the "update" operation. + */ + public ResponseData deactivateWeId(String domain, String weId, Boolean state); + + /** + * get several weId. + * + * @param domain the domain of the data. + * @param first the first index of weId. + * @param last the last index of weId. + * @return execute status of the "update" operation. + */ + public ResponseData> getWeIdList(String domain, Integer first, Integer last); + + /** + * get total amounts of weId. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getWeIdCount(String domain); + + /** + * query Cpt from storage by cptId. + * + * @param domain the domain of the cpt. + * @param cptId the cptId. + * @return the data you stored. + */ + public ResponseData getCpt(String domain, int cptId); + /** + * save Cpt to storage with cptId. + * + * @param domain the domain of the cpt. + * @param cptId the cptId. + * @param publisher the publisher of the cpt. + * @param description the description of the cpt. + * @param cptSchema the cptSchema of the cpt. + * @param cptSignature the cptSignature of the cpt. + * @return the data you stored. + */ + public ResponseData addCpt(String domain, int cptId, String publisher, String description, String cptSchema, String cptSignature); + /** + * query Policy from storage by policyId. + * + * @param domain the domain of the Policy. + * @param policyId the policyId. + * @return the data you stored. + */ + public ResponseData getPolicy(String domain, int policyId); + /** + * save Policy to storage with policyId. + * + * @param domain the domain of the Policy. + * @param policyId the policyId. + * @param publisher the publisher of the Policy. + * @param description the description of the Policy. + * @param cptSchema the cptSchema of the Policy. + * @param cptSignature the cptSignature of the Policy. + * @return the data you stored. + */ + public ResponseData addPolicy(String domain, int policyId, String publisher, String description, String cptSchema, String cptSignature); + /** + * query presentation from storage by presentationId. + * + * @param domain the domain of the presentation. + * @param presentationId the presentationId. + * @return the data you stored. + */ + public ResponseData getPresentation(String domain, int presentationId); + /** + * save Policy to storage with policyId. + * + * @param domain the domain of the presentation. + * @param presentationId the presentationId. + * @param creator the creator of the presentation. + * @param policies the policies of the presentation. + * @return the data you stored. + */ + public ResponseData addPresentation(String domain, int presentationId, String creator, String policies); + /** + * update Cpt to storage with cptId. + * + * @param domain the domain of the cpt. + * @param cptId the cptId. + * @param cptVersion the cptVersion of the cpt. + * @param publisher the publisher of the cpt. + * @param description the description of the cpt. + * @param cptSchema the cptSchema of the cpt. + * @param cptSignature the cptSignature of the cpt. + * @return the data you stored. + */ + public ResponseData updateCpt(String domain, int cptId, int cptVersion, String publisher, String description, String cptSchema, String cptSignature); + /** + * save Cpt to storage with cptId. + * + * @param domain the domain of the cpt. + * @param cptId the cptId. + * @param credentialPublicKey the publicKey of credential template. + * @param credentialProof the proof of credential template. + * @return the data you stored. + */ + public ResponseData updateCredentialTemplate(String domain, int cptId, String credentialPublicKey, String credentialProof); + /** + * save Cpt to storage with cptId. + * + * @param domain the domain of the cpt. + * @param cptId the cptId. + * @param policies the policy id list. + * @return the data you stored. + */ + public ResponseData updateCptClaimPolicies(String domain, int cptId, String policies); + /** + * get several cptId. + * + * @param domain the domain of the data. + * @param first the first index of cptId. + * @param last the last index of cptId. + * @return execute status of the "update" operation. + */ + public ResponseData> getCptIdList(String domain, Integer first, Integer last); + /** + * get total amounts of cpt. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getCptCount(String domain); + /** + * get several policyId. + * + * @param domain the domain of the data. + * @param first the first index of policyId. + * @param last the last index of policyId. + * @return execute status of the "update" operation. + */ + public ResponseData> getPolicyIdList(String domain, Integer first, Integer last); + /** + * get total amounts of policy. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getPolicyCount(String domain); + /** + * add authority issuer to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param name which you want to store to the storage. + * @param desc which you want to store to the storage. + * @param accValue which you want to store to the storage. + * @param extraStr which you want to store to the storage. + * @param extraInt which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData addAuthorityIssuer(String domain, String weId, String name, String desc, String accValue, String extraStr, String extraInt); + /** + * remove authority issuer from storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @return execute status of the "add" operation. + */ + public ResponseData removeAuthorityIssuer(String domain, String weId); + + /** + * query authority issuer by weid. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @return execute status of the "add" operation. + */ + public ResponseData getAuthorityIssuerByWeId(String domain, String weId); + + /** + * query authority issuer by name. + * + * @param domain the domain of the data. + * @param name which you want to store to the storage. + * @return execute status of the "add" operation. + */ + public ResponseData getAuthorityIssuerByName(String domain, String name); + + /** + * updateRole role for weId to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param recognize whether recognize or not + * @return execute status of the "add" operation. + */ + public ResponseData updateAuthorityIssuer(String domain, String weId, Integer recognize); + + /** + * get total AuthorityIssuer. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getAuthorityIssuerCount(String domain); + + /** + * get total recognized AuthorityIssuer. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getRecognizedIssuerCount(String domain); + + /** + * add role for weId to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param roleValue which kind of role you want to add for weId. + * @return execute status of the "add" operation. + */ + public ResponseData addRole(String domain, String weId, Integer roleValue); + + /** + * query role by weId. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @return execute status of the "add" operation. + */ + public ResponseData getRole(String domain, String weId); + + /** + * updateRole role for weId to storage. + * + * @param domain the domain of the data. + * @param weId the key of the data. + * @param roleValue which kind of role you want to add for weId. + * @return execute status of the "add" operation. + */ + public ResponseData updateRole(String domain, String weId, Integer roleValue); + + /** + * add SpecificType with typeName to storage. + * + * @param domain the domain of the data. + * @param typeName the typeName of the SpecificType. + * @param owner the owner of the SpecificType + * @return execute status of the "add" operation. + */ + public ResponseData addSpecificType(String domain, String typeName, String owner); + + /** + * query SpecificType by typeName. + * + * @param domain the domain of the data. + * @param typeName the typeName of the SpecificType. + * @return execute status of the "add" operation. + */ + public ResponseData getSpecificType(String domain, String typeName); + + /** + * remove authority issuer from storage. + * + * @param domain the domain of the data. + * @param typeName the key of the data. + * @return execute status of the "add" operation. + */ + public ResponseData removeSpecificType(String domain, String typeName); + + /** + * updateRole role for weId to storage. + * + * @param domain the domain of the data. + * @param typeName the key of the data. + * @param fellow new fellow list of this specific type + * @return execute status of the "add" operation. + */ + public ResponseData updateSpecificTypeFellow(String domain, String typeName, String fellow); + + /** + * get total IssuerType. + * + * @param domain the domain of the data. + * @return execute status of the "update" operation. + */ + public ResponseData getIssuerTypeCount(String domain); + + /** + * get several cptId. + * + * @param domain the domain of the data. + * @param first the first index of cptId. + * @param last the last index of cptId. + * @return execute status of the "update" operation. + */ + public ResponseData> getIssuerTypeList(String domain, Integer first, Integer last); + + /** + * add evidence with hashValue to storage. + * + * @param domain the domain of the data. + * @param hashValue the hashValue of the evidence. + * @param signer the signer of the evidence + * @param signature the signature of the evidence + * @param log the log of the evidence. + * @param updated the updated of the evidence. + * @param revoked the revoked of the evidence. + * @param extraKey the extraKey of the evidence. + * @param group_id the group_id of the evidence. + * @return execute status of the "add" operation. + */ + public ResponseData addEvidenceByHash(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey, String group_id); + + /** + * query evidence by hash. + * + * @param domain the domain of the data. + * @param hash the key of the data. + * @return execute status of the "add" operation. + */ + public ResponseData getEvidenceByHash(String domain, String hash); + + /** + * update evidence with log and signature to storage. + * + * @param domain the domain of the data. + * @param hashValue the hashValue of the evidence. + * @param signer the signer of the evidence. + * @param signature the signature of the evidence + * @param log the log of the evidence. + * @param updated the updated of the evidence. + * @param revoked the revoked of the evidence. + * @param extraKey the revoked of the evidence. + * @return execute status of the "add" operation. + */ + public ResponseData addSignatureAndLogs(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey); + + /** + * query evidence by hash. + * + * @param domain the domain of the data. + * @param extraKey the extraKey of the data. + * @return execute status of the "add" operation. + */ + public ResponseData getEvidenceByExtraKey(String domain, String extraKey); +} diff --git a/src/main/java/com/webank/weid/suite/persistence/PersistenceFactory.java b/src/main/java/com/webank/weid/suite/persistence/PersistenceFactory.java new file mode 100644 index 00000000..41906fbe --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/PersistenceFactory.java @@ -0,0 +1,54 @@ + + +package com.webank.weid.suite.persistence; + +import com.webank.weid.suite.persistence.ipfs.driver.IpfsDriver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.suite.persistence.mysql.driver.MysqlDriver; +import com.webank.weid.suite.persistence.redis.driver.RedisDriver; + +/** + * 数据库工厂, 根据不同类型的数据库得到相应的数据库. + * @author karenli + * + */ +public class PersistenceFactory { + + private static final Logger logger = LoggerFactory.getLogger(PersistenceFactory.class); + + private static Persistence newMysqlDriver() { + return new MysqlDriver(); + } + + private static Persistence newRedisDriver() { + return new RedisDriver(); + } + private static Persistence newIpfsDriver() { + return new IpfsDriver(); + } + + /** + * 根据封装类型实例化对应的实例对象, 此方法目前支持Mysql, Redis. + * @param persistenceType 封装类型枚举 + * @return 返回具体处理类型 + */ + public static Persistence build(PersistenceType persistenceType) { + switch (persistenceType) { + case Mysql: + return newMysqlDriver(); + case Redis: + return newRedisDriver(); + case Ipfs: + return newIpfsDriver(); + default: + logger.error("the type = {} unsupported.", persistenceType.name()); + throw new WeIdBaseException(ErrorCode.THIS_IS_UNSUPPORTED); + } + } + + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/PersistenceType.java b/src/main/java/com/webank/weid/suite/persistence/PersistenceType.java new file mode 100644 index 00000000..13888868 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/PersistenceType.java @@ -0,0 +1,7 @@ + + +package com.webank.weid.suite.persistence; + +public enum PersistenceType { + Mysql, Ipfs, Redis +} diff --git a/src/main/java/com/webank/weid/suite/persistence/PolicyValue.java b/src/main/java/com/webank/weid/suite/persistence/PolicyValue.java new file mode 100644 index 00000000..7ecc4d68 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/PolicyValue.java @@ -0,0 +1,62 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class PolicyValue { + /** + * 主键,cptId. + */ + private int policy_id; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * 数据版本. + */ + private int policy_version; + + /** + * cpt创建者. + */ + private String publisher; + + /** + * cpt描述. + */ + private String description; + + /** + * cpt对象的json序列化. + */ + private String policy_schema; + + /** + * cpt签名 + */ + private String policy_signature; + + /** + * credential验证公钥 + */ + private String credential_publicKey; + + /** + * credential证明 + */ + private String credential_proof; + /** + * claim policies列表 + */ + private String claim_policies; +} diff --git a/src/main/java/com/webank/weid/suite/persistence/PresentationValue.java b/src/main/java/com/webank/weid/suite/persistence/PresentationValue.java new file mode 100644 index 00000000..e7883a61 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/PresentationValue.java @@ -0,0 +1,21 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +@Data +public class PresentationValue { + /** + * 主键,presentationId. + */ + private int presentation_id; + + /** + * presentation创建者. + */ + private String creator; + + /** + * claim policies列表 + */ + private String claim_policies; +} diff --git a/src/main/java/com/webank/weid/suite/persistence/RoleValue.java b/src/main/java/com/webank/weid/suite/persistence/RoleValue.java new file mode 100644 index 00000000..fcecd02e --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/RoleValue.java @@ -0,0 +1,38 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class RoleValue { + /** + * 主键,weid. + */ + private String weid; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * 是否是authority_role. + */ + private int authority_role; + + /** + * 是否是committee_role. + */ + private int committee_role; + + /** + * 是否是admin_role. + */ + private int admin_role; +} diff --git a/src/main/java/com/webank/weid/suite/persistence/SpecificTypeValue.java b/src/main/java/com/webank/weid/suite/persistence/SpecificTypeValue.java new file mode 100644 index 00000000..09de6892 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/SpecificTypeValue.java @@ -0,0 +1,33 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class SpecificTypeValue { + /** + * 主键,type_name. + */ + private String type_name; + + /** + * SpecificType从属weid. + */ + private String fellow; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * SpecificType拥有者. + */ + private String owner; +} diff --git a/src/main/java/com/webank/weid/suite/persistence/WeIdDocumentValue.java b/src/main/java/com/webank/weid/suite/persistence/WeIdDocumentValue.java new file mode 100644 index 00000000..ca673eb6 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/WeIdDocumentValue.java @@ -0,0 +1,39 @@ +package com.webank.weid.suite.persistence; + +import lombok.Data; + +import java.util.Date; + +@Data +public class WeIdDocumentValue { + /** + * 主键,weid. + */ + private String weid; + + /** + * 创建时间. + */ + private Date created; + + /** + * 更新时间. + */ + private Date updated; + + /** + * 数据版本. + */ + private int version; + + /** + * 是否被注销. + */ + private int deactivated; + + /** + * WeIdDocument对象的json序列化. + */ + private String document_schema; + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsConfig.java b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsConfig.java new file mode 100644 index 00000000..1559dd3d --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsConfig.java @@ -0,0 +1,25 @@ +package com.webank.weid.suite.persistence.ipfs; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.util.PropertyUtils; +import io.ipfs.api.IPFS; + +/** + * ipfs配置类 + * + * @author 刘家辉 + * @date 2023/08/24 + */ +public class IpfsConfig { + + /** + *API地址 + */ + private static final String IPFS_API = PropertyUtils.getProperty( + DataDriverConstant.IPFS_API); + + public IPFS ipfsClient(){ + return new IPFS(IPFS_API); + } + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsDomain.java b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsDomain.java new file mode 100644 index 00000000..645b8ce1 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsDomain.java @@ -0,0 +1,59 @@ +package com.webank.weid.suite.persistence.ipfs; + + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.suite.persistence.BaseDomain; +import com.webank.weid.util.PropertyUtils; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author 刘家辉 + * @date 2023/08/23 + */ +@Getter +public class IpfsDomain extends BaseDomain { + + private static final Logger logger = LoggerFactory.getLogger(com.webank.weid.suite.persistence.redis.RedisDomain.class); + + public IpfsDomain() { + resolveDomain(); + } + + public IpfsDomain(String domainkey) { + this.key = domainkey; + resolveDomain(); + } + + private void resolveDomain() { + + if (StringUtils.isBlank(this.key)) { + this.key = DataDriverConstant.DOMAIN_DEFAULT_INFO; + } + this.value = PropertyUtils.getProperty(this.key); + + if (StringUtils.isBlank(this.value) + && DataDriverConstant.DOMAIN_DEFAULT_INFO.equals(this.key)) { + this.tableDomain = DEFAULT_TABLE; + + } else if (StringUtils.isNotBlank(this.value) + && this.value.split(VALUE_SPLIT_CHAR).length == 2) { + String[] domains = this.value.split(VALUE_SPLIT_CHAR); + this.baseDomain = domains[0]; + this.tableDomain = domains[1]; + } else if (this.key.equals(DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO)) { + this.tableDomain = DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO; + } else { + logger.error("[resolveDomain] the domain {{}:{}} is illegal.", + this.key, + this.value + ); + throw new WeIdBaseException(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL); + } + resolveDomainTimeout(); + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsExecutor.java b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsExecutor.java new file mode 100644 index 00000000..b734557b --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/ipfs/IpfsExecutor.java @@ -0,0 +1,322 @@ +package com.webank.weid.suite.persistence.ipfs; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.suite.persistence.DefaultValue; +import com.webank.weid.util.DataDriverUtils; +import com.webank.weid.util.DataToolUtils; +import io.ipfs.api.IPFS; +import org.apache.commons.collections4.CollectionUtils; +import org.redisson.client.RedisException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * ipfs操作辅助类 + * + * @author 刘家辉 + * @date 2023/08/24 + */ +public class IpfsExecutor { + private static final Logger logger = LoggerFactory.getLogger( + IpfsExecutor.class); + + private IpfsDomain ipfsDomain; + private String path; + + + + /** + * 根据domain创建ipfs执行器. + * + * @param ipfsDomain 域 + */ + public IpfsExecutor(IpfsDomain ipfsDomain) { + if (ipfsDomain != null) { + this.ipfsDomain = ipfsDomain; + //通过domain自动获得写入的path + path=DataDriverConstant.IPFS_BASE_PATH+ipfsDomain.getTableDomain()+".json"; + } else { + this.ipfsDomain = new IpfsDomain(); + } + } + + /** + * 执行查询单个的方法 + * + * @param datakey key + * @param client 客户端 + * @return 返回查询到的数据 + */ + public ResponseData executeQuery(String datakey, + IPFS client) { + + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + Map jsons = DataToolUtils.readFromLocal(path); + String cid = jsons.get(datakey); + if(cid!=null){ + String str = DataDriverUtils.downloadIpfs(client, jsons.get(datakey)); + result.setResult(str); + } + result.setErrorCode(ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", ipfsDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + /** + * 执行分页查询的方法 + * + * @param datas 数据 + * @param client 客户端 + * @return 返回查询到的list集合 + */ + public ResponseData> executeQueryLines(int[] datas, IPFS client) { + + ResponseData> result = new ResponseData>(); + ArrayList list = new ArrayList<>(); + try { + if (client == null) { + return new ResponseData<>(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + + } + Map jsons = DataToolUtils.readFromLocal(path); + //分页查询id或分页查询完整数据 + switch (datas[2]){ + case DataDriverConstant.IPFS_ONLY_ID_LINES: + for (Map.Entry entry : jsons.entrySet()) { + if (entry.getKey().compareTo(String.valueOf(datas[0])) >= 0 && entry.getKey().compareTo(String.valueOf(datas[1])) < 0) { + // 遍历 范围之间的entry + list.add(entry.getValue()); + } + } + break; + case DataDriverConstant.IPFS_READ_CID_LINES: + for (Map.Entry entry : jsons.entrySet()) { + if (entry.getKey().compareTo(String.valueOf(datas[0])) >= 0 && entry.getKey().compareTo(String.valueOf(datas[1])) < 0) { + list.add(DataDriverUtils.downloadIpfs(client,jsons.get(entry.getValue()))); + } + } + break; + default: throw new Exception(); + } + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(list); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", ipfsDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + /** + * 统计数据总数 + * + * @param client 客户端 + * @return 返回数据 + */ + public ResponseData executeQueryCount(IPFS client) { + + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + Map jsons = DataToolUtils.readFromLocal(path); + int count = jsons.size() / 2; + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(count); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", ipfsDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + + /** + * 增加更新的执行方法 + * + * @param client 客户端 + * @param dataKey key + * @param datas 数据 + * @return 返回是否执行成功 + */ + public ResponseData execute(IPFS client,String dataKey,Object... datas) { + + ResponseData result = new ResponseData<>(); + try { + if (client == null) { + return + new ResponseData<>(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + TransactionArgs transactionArgs = new TransactionArgs(); + DefaultValue value = new DefaultValue(); + //本地取json文件 + Map jsons = DataToolUtils.readFromLocal(path); + //分transaction update insert 三种情况 + if (datas.length == 6) { + transactionArgs.setRequestId((String) datas[0]); + transactionArgs.setMethod((String) datas[1]); + transactionArgs.setArgs((String) datas[2]); + transactionArgs.setTimeStamp((Long) datas[3]); + transactionArgs.setExtra((String)datas[4]); + transactionArgs.setBatch((String)datas[5]); + String valueString = DataToolUtils.serialize(transactionArgs); + jsons.put(dataKey,DataDriverUtils.uploadIpfs(client,valueString.getBytes())); + jsons.put(String.valueOf((jsons.size())/2),dataKey); + DataToolUtils.writeInLocal(path,jsons); + } else { + value.setData((String) datas[0]); + value.setId(dataKey); + value.setExpire(ipfsDomain.getExpire()); + if (datas.length == 3) { + value.setCreated((Date)datas[1]); + value.setUpdated((Date)datas[2]); + //datas.lenth==2时为UpDate + } else if (datas.length == 2) { + value.setUpdated((Date)datas[1]); + } + //解决重复写问题 + if (datas.length == 3 && jsons.get(dataKey) != null) { + return + new ResponseData<>( + DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + value.setExt1((jsons.size()+1)/2); + //转化为json文件以便上传至ipfs + String valueString = DataToolUtils.serialize(value); + //本地存储cid码 + jsons.put(dataKey,DataDriverUtils.uploadIpfs(client, valueString.getBytes())); + //存储index 方便分页查询 + jsons.put(String.valueOf((jsons.size())/2),dataKey); + DataToolUtils.writeInLocal(path,jsons); + } + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_SUCESS_STATUS); + + } catch (Exception e) { + logger.error("Update data into {{}} with exception", ipfsDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } + + + /** + * 批量添加 + * + * @param dataList 数据列表 + * @param client 客户端 + * @return {@link ResponseData}<{@link Integer}> + */ + public ResponseData batchAdd(List> dataList, IPFS client) { + + ResponseData result = new ResponseData(); + List value = new ArrayList<>(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + Map jsons = DataToolUtils.readFromLocal(path); + List values = dataList.get(dataList.size() - 1); + int size = values.size(); + for (List list : dataList) { + if (CollectionUtils.isEmpty(list) || list.size() != size) { + return + new ResponseData( + DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_BATCH_ADD_DATA_MISMATCH + ); + } + } + + for (int i = 0; i < size; i++) { + DefaultValue val = new DefaultValue(); + val.setId((String) dataList.get(0).get(i)); + val.setData((String)dataList.get(1).get(i)); + val.setExpire((Date)dataList.get(2).get(i)); + val.setCreated((Date)dataList.get(3).get(i)); + val.setUpdated((Date)dataList.get(4).get(i)); + value.add(val); + } + + for (DefaultValue val : value) { + val.setExt1((jsons.size()+1)/2); + String valueString = DataToolUtils.serialize(val); + String cid = DataDriverUtils.uploadIpfs(client, valueString.getBytes()); + jsons.put(val.getId(),cid); + jsons.put(String.valueOf((jsons.size())/2),val.getId()); + } + DataToolUtils.writeInLocal(path,jsons); + result.setResult(size); + } catch (RedisException e) { + logger.error("Batch add data to {{}} with exception", ipfsDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } catch (IOException e) { + logger.error("read data form local to {{}} with exception", ipfsDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } + + /** + * 执行删除方法 + * + * @param dataKey key + * @param client 客户端 + * @return {@link ResponseData}<{@link Integer}> + */ + public ResponseData executeDelete(String dataKey, IPFS client) { + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + Map jsons = DataToolUtils.readFromLocal(path); + if (jsons.get(dataKey)== null) { + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } else { + String cid = jsons.get(dataKey); + String value = DataDriverUtils.downloadIpfs(client, cid); + DefaultValue deserialize = DataToolUtils.deserialize(value, DefaultValue.class); + //以null作为删除标记 + jsons.put(dataKey,null); + jsons.put(String.valueOf(deserialize.getExt1()),null); + DataToolUtils.writeInLocal(path,jsons); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_SUCESS_STATUS); + } + } catch (Exception e) { + logger.error("Delete data into {{}} with exception", ipfsDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } +} + diff --git a/src/main/java/com/webank/weid/suite/persistence/ipfs/driver/IpfsDriver.java b/src/main/java/com/webank/weid/suite/persistence/ipfs/driver/IpfsDriver.java new file mode 100644 index 00000000..a325e646 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/ipfs/driver/IpfsDriver.java @@ -0,0 +1,614 @@ +package com.webank.weid.suite.persistence.ipfs.driver; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.WeIdDocument; +import com.webank.weid.blockchain.protocol.base.WeIdDocumentMetadata; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.suite.persistence.*; +import com.webank.weid.suite.persistence.ipfs.IpfsConfig; +import com.webank.weid.suite.persistence.ipfs.IpfsDomain; +import com.webank.weid.suite.persistence.ipfs.IpfsExecutor; +import com.webank.weid.util.DataDriverUtils; +import com.webank.weid.util.DataToolUtils; +import io.ipfs.api.IPFS; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +/** + *因与redis存储方式类似 所以在实现方面借鉴了redis实现类 + * @author uwepppp + * @date 2023/08/21 + */ +public class IpfsDriver implements Persistence { + private static final Logger logger = LoggerFactory.getLogger( + IpfsDriver.class); + + private static final Integer FAILED_STATUS = DataDriverConstant.IPFS_EXECUTE_FAILED_STATUS; + + private static final ErrorCode KEY_INVALID = ErrorCode.PRESISTENCE_DATA_KEY_INVALID; + + public IpfsConfig config =new IpfsConfig(); + IPFS client =config.ipfsClient(); + + /** + * 添加方法 + * @param domain 数据域 + * @param id 存储id + * @param data 数据 + * @return {@link ResponseData}<{@link Integer}> + */ + @Override + public ResponseData add(String domain, String id, String data) { + + if (StringUtils.isEmpty(id)) { + logger.error("[ipfs->add] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + Date date = new Date(); + Object[] datas = {data, date, date}; + return new IpfsExecutor(ipfsDomain).execute(client, dataKey, datas); + } catch (WeIdBaseException e) { + logger.error("[ipfs->add] add the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + /** + * 批量添加 + * @param domain + * @param keyValueList + * @return {@link ResponseData}<{@link Integer}> + */ + @Override + public ResponseData batchAdd(String domain, Map keyValueList) { + + try { + List idHashList = new ArrayList<>(); + List dataList = new ArrayList<>(); + for (String id : keyValueList.keySet()) { + String data = keyValueList.get(id); + if (StringUtils.isEmpty(id)) { + logger.error("[ipfs->batchAdd] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + idHashList.add(DataToolUtils.hash(id)); + dataList.add(data); + } + IpfsDomain ipfsDomain = new IpfsDomain(domain); + List> dataLists = new ArrayList>(); + dataLists.add(idHashList); + dataLists.add(Arrays.asList(dataList.toArray())); + //处理失效时间 + dataLists.add(fixedListWithDefault(idHashList.size(), ipfsDomain.getExpire())); + //处理创建时间和更新时间 + List nowList = fixedListWithDefault(idHashList.size(), ipfsDomain.getNow()); + dataLists.add(nowList); + dataLists.add(nowList); + return new IpfsExecutor(ipfsDomain).batchAdd(dataLists, client); + } catch (WeIdBaseException e) { + logger.error("[ipfs->batchAdd] batchAdd the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + private List fixedListWithDefault(int size, Object obj) { + + Object[] dates = new Object[size]; + Arrays.fill(dates, obj); + List list = new ArrayList<>(); + list.addAll(Arrays.asList(dates)); + return list; + } + + /** + * 获取方法 + * @param domain + * @param id + * @return {@link ResponseData}<{@link String}> + */ + @Override + public ResponseData get(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[ipfs->get] the id of the data is empty."); + return new ResponseData(StringUtils.EMPTY, KEY_INVALID); + } + //dataKey:id的hash值 + String dataKey = DataToolUtils.hash(id); + try { + ResponseData result = new ResponseData(); + //设置result初始值为空字符串 + result.setResult(StringUtils.EMPTY); + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQuery(dataKey, client); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + DefaultValue data = DataToolUtils.deserialize( + response.getResult(), DefaultValue.class); + //超过超时时间,log输出data超时 + if (data != null && data.getExpire() != null + && data.getExpire().before(new Date())) { + logger.error("[ipfs->get] the data is expire."); + //输出empty以及超过超时时间错误代码 + return new ResponseData(StringUtils.EMPTY, + ErrorCode.PERSISTENCE_DATA_EXPIRE); + } + if (data != null && StringUtils.isNotBlank(data.getData())) { + result.setResult( + new String( + data.getData().getBytes( + DataDriverConstant.STANDARDCHARSETS_ISO), + DataDriverConstant.STANDARDCHARSETS_UTF_8 + ) + ); + } + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[ipfs->get] get the data error.", e); + return new ResponseData(StringUtils.EMPTY, e.getErrorCode()); + } + } + + /** + * 删除方法 + * @param domain + * @param id + * @return {@link ResponseData}<{@link Integer}> + */ + @Override + public ResponseData delete(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[ipfs->delete] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + return new IpfsExecutor(ipfsDomain).executeDelete(dataKey, client); + } catch (WeIdBaseException e) { + logger.error("[ipfs->delete] delete the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData update(String domain, String id, String data) { + + if (StringUtils.isEmpty(id) || StringUtils.isBlank(this.get(domain, id).getResult())) { + logger.error("[ipfs->update] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + Date date = new Date(); + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + Object[] datas = {data, date}; + return new IpfsExecutor(ipfsDomain).execute(client, dataKey,datas); + } catch (WeIdBaseException e) { + logger.error("[ipfs->update] update the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addOrUpdate(String domain, String id, String data) { + + ResponseData getRes = this.get(domain, id); + //如果查询数据存在,或者失效 则进行更新 否则进行新增 + if ((StringUtils.isNotBlank(getRes.getResult()) + && getRes.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) + || + getRes.getErrorCode().intValue() == ErrorCode.PERSISTENCE_DATA_EXPIRE.getCode()) { + return this.update(domain, id, data); + } + return this.add(domain, id, data); + } + + @Override + public ResponseData addTransaction(TransactionArgs transactionArgs) { + + if (StringUtils.isEmpty(transactionArgs.getRequestId())) { + logger.error("[ipfs->add] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + IpfsDomain ipfsDomain = new IpfsDomain( + DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO); + String datakey = transactionArgs.getRequestId(); + Object[] datas = { + transactionArgs.getRequestId(), + transactionArgs.getMethod(), + transactionArgs.getArgs(), + transactionArgs.getTimeStamp(), + transactionArgs.getExtra(), + transactionArgs.getBatch() + }; + return new IpfsExecutor(ipfsDomain).execute(client, datakey, datas); + } catch (WeIdBaseException e) { + logger.error("[ipfs->add] add the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addWeId(String domain, String weId, String documentSchema) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[ipfs->addWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + Date now = ipfsDomain.getNow(); + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setUpdated(now); + value.setCreated(now); + value.setDeactivated(0); + value.setDocument_schema(documentSchema); + String data = DataToolUtils.serialize(value); + //将要存入的对象封装为data + return add(domain,weId,data); + } catch (WeIdBaseException e) { + logger.error("[ipfs->addWeId] add the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateWeId(String domain, String weId, String documentSchema) { + if (StringUtils.isEmpty(weId)) { + logger.error("[ipfs->updateWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + Date date = new Date(); + String dataKey = DataToolUtils.hash(weId); + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQuery(dataKey, client); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj( + response.getResult(), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[ipfs->updateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + int version = tableData.getVersion(); + version++; + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setUpdated(date); + value.setCreated(tableData.getCreated()); + value.setDeactivated(tableData.getDeactivated()); + value.setDocument_schema(documentSchema); + value.setVersion(version); + String data = com.webank.weid.blockchain.util.DataToolUtils.serialize(value); + return update(domain,weId,data); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[ipfs->updateWeId] update the weid error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdDocument(String domain, String weId) { + if (StringUtils.isEmpty(weId)) { + logger.error("[ipfs->getWeIdDocument] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + try { + String dataKey = DataToolUtils.hash(weId); + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQuery(dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj(response.getResult(), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + return new ResponseData<>(WeIdDocument.fromJson(tableData.getDocument_schema()), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } catch (WeIdBaseException e) { + logger.error("[ipfs->getWeIdDocument] get the weIdDocument error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getMeta(String domain, String weId) { + if (StringUtils.isEmpty(weId)) { + logger.error("[ipfs->getMeta] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + try { + String dataKey = DataToolUtils.hash(weId); + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQuery( dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj(response.getResult(), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + WeIdDocumentMetadata weIdDocumentMetadata = new WeIdDocumentMetadata(); + weIdDocumentMetadata.setCreated(tableData.getCreated().getTime()); + weIdDocumentMetadata.setUpdated(tableData.getUpdated().getTime()); + weIdDocumentMetadata.setVersionId(tableData.getVersion()); + weIdDocumentMetadata.setDeactivated(tableData.getDeactivated() == 1); + return new ResponseData<>(weIdDocumentMetadata, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[ipfs->getMeta] getMeta error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData deactivateWeId(String domain, String weId, Boolean state) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[ipfs->deactivateWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(weId); + Date date = new Date(); + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQuery( dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj( + response.getResult(), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[ipfs->deactivateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setDocument_schema(tableData.getDocument_schema()); + value.setCreated(tableData.getCreated()); + value.setUpdated(date); + value.setVersion(tableData.getVersion()); + value.setDeactivated(state?1:0); + String data = DataToolUtils.serialize(value); + return update(domain,weId,data); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[ipfs->deactivateWeId] deactivate the weId error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData> getWeIdList(String domain, Integer first, Integer last) { + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + int[] datas = {first, last - first + 1,DataDriverConstant.IPFS_ONLY_ID_LINES}; + ResponseData> response = new IpfsExecutor(ipfsDomain).executeQueryLines(datas, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(DataDriverUtils.decodeValueToNeedListJson(response.getResult()), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[ipfs->getWeIdList] get the data error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdCount(String domain) { + try { + IpfsDomain ipfsDomain = new IpfsDomain(domain); + ResponseData response = new IpfsExecutor(ipfsDomain) + .executeQueryCount( client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[ipfs->getWeIdCount] get the data error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + + /** + * 暂未完成 + */ + @Override + public ResponseData getCpt(String domain, int cptId) { + return null; + } + + @Override + public ResponseData addCpt(String domain, int cptId, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData getPolicy(String domain, int policyId) { + return null; + } + + @Override + public ResponseData addPolicy(String domain, int policyId, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData getPresentation(String domain, int presentationId) { + return null; + } + + @Override + public ResponseData addPresentation(String domain, int presentationId, String creator, String policies) { + return null; + } + + @Override + public ResponseData updateCpt(String domain, int cptId, int cptVersion, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData updateCredentialTemplate(String domain, int cptId, String credentialPublicKey, String credentialProof) { + return null; + } + + @Override + public ResponseData updateCptClaimPolicies(String domain, int cptId, String policies) { + return null; + } + + @Override + public ResponseData> getCptIdList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData getCptCount(String domain) { + return null; + } + + @Override + public ResponseData> getPolicyIdList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData getPolicyCount(String domain) { + return null; + } + + @Override + public ResponseData addAuthorityIssuer(String domain, String weId, String name, String desc, String accValue, String extraStr, String extraInt) { + return null; + } + + @Override + public ResponseData removeAuthorityIssuer(String domain, String weId) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerByWeId(String domain, String weId) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerByName(String domain, String name) { + return null; + } + + @Override + public ResponseData updateAuthorityIssuer(String domain, String weId, Integer recognize) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerCount(String domain) { + return null; + } + + @Override + public ResponseData getRecognizedIssuerCount(String domain) { + return null; + } + + @Override + public ResponseData addRole(String domain, String weId, Integer roleValue) { + return null; + } + + @Override + public ResponseData getRole(String domain, String weId) { + return null; + } + + @Override + public ResponseData updateRole(String domain, String weId, Integer roleValue) { + return null; + } + + @Override + public ResponseData addSpecificType(String domain, String typeName, String owner) { + return null; + } + + @Override + public ResponseData getSpecificType(String domain, String typeName) { + return null; + } + + @Override + public ResponseData removeSpecificType(String domain, String typeName) { + return null; + } + + @Override + public ResponseData updateSpecificTypeFellow(String domain, String typeName, String fellow) { + return null; + } + + @Override + public ResponseData getIssuerTypeCount(String domain) { + return null; + } + + @Override + public ResponseData> getIssuerTypeList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData addEvidenceByHash(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey, String group_id) { + return null; + } + + @Override + public ResponseData getEvidenceByHash(String domain, String hash) { + return null; + } + + @Override + public ResponseData addSignatureAndLogs(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey) { + return null; + } + + @Override + public ResponseData getEvidenceByExtraKey(String domain, String extraKey) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/suite/persistence/mysql/ConnectionPool.java b/src/main/java/com/webank/weid/suite/persistence/mysql/ConnectionPool.java new file mode 100644 index 00000000..631c6f95 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/mysql/ConnectionPool.java @@ -0,0 +1,269 @@ + + +package com.webank.weid.suite.persistence.mysql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedList; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.dbcp2.BasicDataSource; +import org.apache.commons.dbcp2.BasicDataSourceFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.util.PropertyUtils; + +public class ConnectionPool { + + private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class); + + private static Map connectionPoolMap = new ConcurrentHashMap<>(); + + private static final LinkedList SOURCE_NAME_LIST = new LinkedList(); + + static { + init(); + } + + private ConnectionPool() { + + } + + /** + * 初始化连接池配置. + * + * @return 返回配置对象 + */ + private static Properties initProperties(String dsNamePrefix) { + // 连接URL + String dbUrl = PropertyUtils.getProperty(dsNamePrefix + DataDriverConstant.JDBC_URL); + // 驱动名称 + String driverNameKey = dsNamePrefix + DataDriverConstant.JDBC_DRIVER; + String driverClass = PropertyUtils.getProperty( + driverNameKey, + DataDriverConstant.POOL_DRIVER_NAME_DEFAULT_VALUE + ); + // 用户名 + String userNameKey = dsNamePrefix + DataDriverConstant.JDBC_USER_NAME; + String userName = PropertyUtils.getProperty(userNameKey); + // 密码 + String passWordKey = dsNamePrefix + DataDriverConstant.JDBC_USER_PASSWORD; + String passWord = PropertyUtils.getProperty(passWordKey); + // 最大活跃链接 + String maxActiveKey = dsNamePrefix + DataDriverConstant.JDBC_MAX_ACTIVE; + String maxActive = PropertyUtils.getProperty( + maxActiveKey, + DataDriverConstant.POOL_MAX_ACTIVE_DEFAULT_VALUE + ); + // 最小空闲链接 + String minIdleKey = dsNamePrefix + DataDriverConstant.JDBC_MIN_IDLE; + String minIdle = PropertyUtils.getProperty( + minIdleKey, + DataDriverConstant.POOL_MIN_IDLE_DEFAULT_VALUE + ); + // 最大空闲链接 + String maxIdleKey = dsNamePrefix + DataDriverConstant.JDBC_MAX_IDLE; + String maxIdle = PropertyUtils.getProperty( + maxIdleKey, + DataDriverConstant.POOL_MAX_IDLE_DEFAULT_VALUE + ); + // 获取链接的最大等待时间 + String maxWaitKey = dsNamePrefix + DataDriverConstant.JDBC_MAX_WAIT; + String maxWait = PropertyUtils.getProperty( + maxWaitKey, + DataDriverConstant.POOL_MAX_WAIT_DEFAULT_VALUE + ); + // 轮询检查连接间隔时间 + String timeBetweenKey = dsNamePrefix + DataDriverConstant.JDBC_TIME_BETWEEN_ERM; + String timeBetween = PropertyUtils.getProperty( + timeBetweenKey, + DataDriverConstant.POOL_TIME_BETWEEN_ERM_DEFAULT_VALUE + ); + // 单次检查连接数据 + String numTestsPerErKey = dsNamePrefix + DataDriverConstant.JDBC_NUM_TEST_PER_ER; + String numTestsPerEr = PropertyUtils.getProperty( + numTestsPerErKey, + DataDriverConstant.POOL_NUM_TEST_PER_ER_DEFAULT_VALUE + ); + // 最小空闲时间的连接将被检查 + String minEitmKey = dsNamePrefix + DataDriverConstant.JDBC_MIN_EITM; + String minEitm = PropertyUtils.getProperty( + minEitmKey, + DataDriverConstant.POOL_MIN_EITM_DEFAULT_VALUE + ); + // 初始化大小 + String initSizeKey = dsNamePrefix + DataDriverConstant.JDBC_INIT_SIZE; + String initSize = PropertyUtils.getProperty( + initSizeKey, + DataDriverConstant.POOL_INIT_DEFAULT_VALUE + ); + Properties p = new Properties(); + p.setProperty(DataDriverConstant.POOL_URL, dbUrl); + p.setProperty(DataDriverConstant.POOL_DRIVER_CLASS_NAME, driverClass); + p.setProperty(DataDriverConstant.POOL_USERNAME, userName); + p.setProperty(DataDriverConstant.POOL_PASSWORD, passWord); + p.setProperty(DataDriverConstant.POOL_MAX_ACTIVE, maxActive); + p.setProperty(DataDriverConstant.POOL_MIN_IDLE, minIdle); + p.setProperty(DataDriverConstant.POOL_MAX_IDLE, maxIdle); + p.setProperty(DataDriverConstant.POOL_MAX_WAIT, maxWait); + p.setProperty(DataDriverConstant.POOL_INITIAL_SIZE, initSize); + // 是否自动回收超时连接 + p.setProperty( + DataDriverConstant.POOL_MAX_REMOVE_ABANDONED, + DataDriverConstant.JDBC_REMOVE_ABANDONED + ); + p.setProperty( + DataDriverConstant.POOL_MAX_REMOVE_MAINTENANCE, + DataDriverConstant.JDBC_REMOVE_ABANDONED + ); + // 是否自动回收超时连接的超时时间 + p.setProperty( + DataDriverConstant.POOL_MAX_REMOVE_ABANDONED_TIMEOUT, + DataDriverConstant.JDBC_REMOVE_ABANDONED_TIMEOUT + ); + // 是否测试借出连接 + p.setProperty( + DataDriverConstant.POOL_TEST_ON_BORROW, + DataDriverConstant.JDBC_TEST_ON_BORROW + ); + // 是否开启定时检查 + p.setProperty( + DataDriverConstant.POOL_TEST_ON_WHILE, + DataDriverConstant.JDBC_TEST_ON_WHILE + ); + p.setProperty(DataDriverConstant.POOL_TIME_BETWEEN_ERM, timeBetween); + p.setProperty(DataDriverConstant.POOL_NUM_TEST_PER_ER, numTestsPerEr); + // 检查连接sql + p.setProperty( + DataDriverConstant.POOL_VALIDATION_QUERY, + DataDriverConstant.JDBC_VALIDATION_QUERY + ); + p.setProperty(DataDriverConstant.POOL_MIN_EITM, minEitm); + return p; + } + + /** + * 初始化连接池. + */ + private static void init() { + try { + String dataSourceNameStr = + PropertyUtils.getProperty(DataDriverConstant.JDBC_DATASOURCE_NAME); + String[] dataSourceNames = dataSourceNameStr.split(","); + for (String string : dataSourceNames) { + SOURCE_NAME_LIST.add(string); + Properties properties = initProperties(string + "."); + BasicDataSource connectionPool = + (BasicDataSource) BasicDataSourceFactory.createDataSource(properties); + connectionPoolMap.put(string, connectionPool); + } + } catch (Exception e) { + logger.error("init ConnectionPool error, please check the log.", e); + } + } + + /** + * 从连接池中获取连接. + * + * @param dsName 数据源名称 + * @return 返回连接对象 + */ + public static Connection getConnection(String dsName) { + Connection conn = null; + try { + conn = connectionPoolMap.get(dsName).getConnection(); + conn.setAutoCommit(true); + } catch (Exception e) { + logger.error("get connection error, please check the log.", e); + } + return conn; + } + + /** + * 关闭数据库连接资源. + * + * @param conn 数据库连接对象 + * @param pstmt 预编译SQL对象 + * @param rs 结果集对象 + */ + public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { + closeResources(rs); + closeResources(pstmt); + closeResources(conn); + } + + /** + * 关闭数据库连接资源. + * + * @param conn 数据库连接对象 + * @param pstmt 预编译SQL对象 + */ + public static void close(Connection conn, PreparedStatement pstmt) { + close(conn, pstmt, null); + } + + /** + * 关闭数据库连接资源. + * + * @param conn 数据库连接对象 + */ + public static void close(Connection conn) { + close(conn, null, null); + } + + private static void closeResources(Connection conn) { + if (conn != null) { + try { + conn.setAutoCommit(true); + conn.close(); + } catch (SQLException e) { + logger.error("close Connection error.", e); + } + } + } + + private static void closeResources(PreparedStatement pstmt) { + if (pstmt != null) { + try { + pstmt.close(); + } catch (SQLException e) { + logger.error("close PreparedStatement error.", e); + } + } + } + + private static void closeResources(ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + logger.error("close ResultSet error.", e); + } + } + } + + /** + * 获取第一个数据源名称. + * + * @return 返回数据源名称 + */ + public static String getFirstDataSourceName() { + return SOURCE_NAME_LIST.getFirst(); + } + + /** + * 检查数据源是否存在. + * + * @param dataSourceName 数据源名称 + * @return 如果存在返回 true, 否则返回 false + */ + public static boolean checkDataSourceName(String dataSourceName) { + return SOURCE_NAME_LIST.contains(dataSourceName); + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/mysql/SqlDomain.java b/src/main/java/com/webank/weid/suite/persistence/mysql/SqlDomain.java new file mode 100644 index 00000000..de11a7bc --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/mysql/SqlDomain.java @@ -0,0 +1,116 @@ + + +package com.webank.weid.suite.persistence.mysql; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.suite.persistence.BaseDomain; +import com.webank.weid.util.PropertyUtils; + +@Getter +public class SqlDomain extends BaseDomain { + + private static final Logger logger = LoggerFactory.getLogger(SqlDomain.class); + + /** + * the split for key. + */ + public static final String KEY_SPLIT_CHAR = "."; + + /** + * the domain prefix. + */ + public static final String DOMAIN_PREFIX = "domain."; + + /** + * the local prefix. + */ + public static final String LOCAL_PREFIX = "local."; + + /** + * 表的默认前缀. + */ + private static final String DEFAULT_TABLE_PREFIX = "weidentity"; + + /** + * 机构编码. + */ + private static final String ORG_ID = PropertyUtils.getProperty("blockchain.orgid"); + + /** + * 表名分隔符. + */ + private static final String TABLE_SPLIT_CHAR = "_"; + + public SqlDomain() { + resolveDomain(); + } + + public SqlDomain(String domainKey) { + this.key = domainKey; + resolveDomain(); + } + + private void resolveDomain() { + if (StringUtils.isBlank(this.key)) { + this.key = DataDriverConstant.DOMAIN_DEFAULT_INFO; + } + this.value = PropertyUtils.getProperty(this.key); + if (StringUtils.isBlank(this.value) + && DataDriverConstant.DOMAIN_DEFAULT_INFO.equals(this.key)) { + this.baseDomain = ConnectionPool.getFirstDataSourceName(); + this.tableDomain = DEFAULT_TABLE; + } else if (StringUtils.isNotBlank(this.value) + && this.value.split(VALUE_SPLIT_CHAR).length == 2) { + String[] domains = this.value.split(VALUE_SPLIT_CHAR); + this.baseDomain = domains[0]; + this.tableDomain = domains[1]; + if (!ConnectionPool.checkDataSourceName(this.baseDomain)) { + logger.error( + "[resolveDomain] the domain {{}:{}} is invalid, {} is not exists.", + this.key, + this.value, + this.baseDomain + ); + throw new WeIdBaseException(ErrorCode.PRESISTENCE_DOMAIN_INVALID); + } + } else { + logger.error("[resolveDomain] the domain {{}:{}} is illegal.", + this.key, + this.value + ); + throw new WeIdBaseException(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL); + } + resolveDomainTimeout(); + } + + /** + * get the table name. + * @return the tableName + */ + public String getTableName() { + if (StringUtils.isBlank(ORG_ID)) { + logger.error("[getTableName] the orgid is blank."); + throw new WeIdBaseException(ErrorCode.ORG_ID_IS_NULL); + } + return new StringBuffer(DEFAULT_TABLE_PREFIX) + .append(TABLE_SPLIT_CHAR) + .append(ORG_ID) + .append(TABLE_SPLIT_CHAR) + .append(this.tableDomain).toString(); + } + + /** + * 设置数据源名称, 目前接口暂时不开放. + * @param baseDomain 数据源名称 + */ + void setBaseDomain(String baseDomain) { + this.baseDomain = baseDomain; + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/mysql/SqlExecutor.java b/src/main/java/com/webank/weid/suite/persistence/mysql/SqlExecutor.java new file mode 100644 index 00000000..f50a12c3 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/mysql/SqlExecutor.java @@ -0,0 +1,614 @@ + + +package com.webank.weid.suite.persistence.mysql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.blockchain.protocol.response.ResponseData; + + +/** + * 数据库操作辅助类. + * + * @author v_wbgyang + */ +public class SqlExecutor { + + /** + * 表占位符. + */ + public static final String TABLE_CHAR = "$1"; + /** + * 库占位符. + */ + public static final String DATABASE_CHAR = "$2"; + /** + * sql for query. + */ + public static final String SQL_QUERY = "select id,data,created,expire from $1 where id =?"; + /** + * sql for add. + */ + public static final String SQL_SAVE = "insert into $1(id, data, expire, created, updated) " + + "values(?,?,?,?,?)"; + /** + * sql for update. + */ + public static final String SQL_UPDATE = "update $1 set updated = ?, data = ?, expire = ? " + + "where id = ?"; + /** + * sql for delete. + */ + public static final String SQL_DELETE = "delete from $1 where id = ?"; + /** + * sql for add transaction. + */ + public static final String SQL_SAVE_TRANSACTION = + "insert into weidentity_offline_transaction_info" + + "(request_id, transaction_method, transaction_args, transaction_timestamp, extra, batch)" + + " values(?,?,?,?,?,?)"; + /** + * sql for query total lines of data. + */ + public static final String SQL_QUERY_TOTAL_LINE = "select COUNT(*) totalCount from $1"; + /** + * sql for query several weId from firstIndex. + */ + public static final String SQL_QUERY_SEVERAL_WEID = "select weid from $1 LIMIT ?, ?"; + /** + * sql for insert weIdDocument and metaDta. + */ + public static final String SQL_SAVE_WEID = "insert into $1 (weid,created,updated,version,deactivated,document_schema) values(?,?,?,?,?,?)"; + /** + * sql for query weIdDocument and metaDta. + */ + public static final String SQL_QUERY_WEID = "select weid,created,updated,version,deactivated,document_schema from $1 where weid=?"; + /** + * sql for update weIdDocument and metaDta. + */ + public static final String SQL_UPDATE_WEID = "update $1 set updated = ?, version = ?, deactivated = ?, document_schema = ? where weid = ?"; + /** + * sql for query cpt. + */ + public static final String SQL_QUERY_CPT = "select cpt_id,created,updated,cpt_version,publisher,description,cpt_schema,cpt_signature,credential_publicKey,credential_proof,claim_policies from $1 where cpt_id =?"; + /** + * sql for insert cpt. + */ + public static final String SQL_SAVE_CPT = "insert into $1 (cpt_id,created,updated,cpt_version,publisher,description,cpt_schema,cpt_signature) values(?,?,?,?,?,?,?,?)"; + /** + * sql for update cpt. + */ + public static final String SQL_UPDATE_CPT = "update $1 set updated = ?, cpt_version = ?, publisher = ?, description = ?, cpt_schema = ?, cpt_signature = ? where cpt_id = ?"; + /** + * sql for update credential template. + */ + public static final String SQL_UPDATE_CREDENTIAL_TEMPLATE = "update $1 set credential_publicKey = ?, credential_proof = ? where cpt_id = ?"; + /** + * sql for update cpt claim policies. + */ + public static final String SQL_UPDATE_CLAIM_POLICIES = "update $1 set claim_policies = ? where cpt_id = ?"; + /** + * sql for query several cpt_id from firstIndex. + */ + public static final String SQL_QUERY_SEVERAL_CPT = "select cpt_id from $1 LIMIT ?, ?"; + /** + * sql for insert policy. + */ + public static final String SQL_SAVE_POLICY = "insert into $1 (policy_id,created,updated,policy_version,publisher,description,policy_schema,policy_signature) values(?,?,?,?,?,?,?,?)"; + /** + * sql for query policy. + */ + public static final String SQL_QUERY_POLICY = "select policy_id,created,updated,policy_version,publisher,description,policy_schema,policy_signature,credential_publicKey,credential_proof,claim_policies from $1 where policy_id =?"; + /** + * sql for query several policy_id from firstIndex. + */ + public static final String SQL_QUERY_SEVERAL_POLICY = "select policy_id from $1 LIMIT ?, ?"; + /** + * sql for insert presentation. + */ + public static final String SQL_SAVE_PRESENTATION = "insert into $1 (presentation_id,creator,claim_policies) values(?,?,?)"; + /** + * sql for query presentation. + */ + public static final String SQL_QUERY_PRESENTATION = "select presentation_id,creator,claim_policies from $1 where presentation_id =?"; + /** + * sql for insert authority issuer. + */ + public static final String SQL_SAVE_AUTHORITY_ISSUER = "insert into $1 (weid,name,description,created,updated,recognize,acc_value,extra_str,extra_int) values(?,?,?,?,?,?,?,?,?)"; + /** + * sql for query authority issuer by weId. + */ + public static final String SQL_QUERY_AUTHORITY_ISSUER_BY_ADDRESS = "select weid,name,description,created,updated,recognize,acc_value,extra_str,extra_int from $1 where weid =?"; + /** + * sql for query authority issuer by name. + */ + public static final String SQL_QUERY_AUTHORITY_ISSUER_BY_NAME = "select weid,name,description,created,updated,recognize,acc_value,extra_str,extra_int from $1 where name =?"; + /** + * sql for delete authority issuer. + */ + public static final String SQL_DELETE_AUTHORITY_ISSUER = "delete from $1 where weid = ?"; + /** + * sql for update authority issuer, only update recognize. + */ + public static final String SQL_UPDATE_AUTHORITY_ISSUER = "update $1 set updated = ?, recognize = ? where weid = ?"; + /** + * sql for query total amount of recognized authority issuer. + */ + public static final String SQL_QUERY_TOTAL_RECOGNIZED_ISSUER = "select COUNT(*) totalCount from $1 where recognize = 1"; + /** + * sql for insert role. + */ + public static final String SQL_SAVE_ROLE = "insert into $1 (weid,created,updated,authority_role,committee_role,admin_role) values(?,?,?,?,?,?)"; + /** + * sql for query role by weId. + */ + public static final String SQL_QUERY_ROLE = "select weid,created,updated,authority_role,committee_role,admin_role from $1 where weid =?"; + /** + * sql for update role. + */ + public static final String SQL_UPDATE_ROLE = "update $1 set updated = ?, authority_role = ?, committee_role = ?, admin_role = ? where weid = ?"; + /** + * sql for insert specific type. + */ + public static final String SQL_SAVE_SPECIFIC_TYPE = "insert into $1 (type_name,created,updated,owner) values(?,?,?,?)"; + /** + * sql for query specific type by type_name. + */ + public static final String SQL_QUERY_SPECIFIC_TYPE = "select type_name,fellow,created,updated,owner from $1 where type_name =?"; + /** + * sql for delete specific type. + */ + public static final String SQL_DELETE_SPECIFIC_TYPE = "delete from $1 where type_name = ?"; + /** + * sql for update specific issuer, only update fellow. + */ + public static final String SQL_UPDATE_SPECIFIC_TYPE_FELLOW = "update $1 set fellow = ? where type_name = ?"; + /** + * sql for query several policy_id from firstIndex. + */ + public static final String SQL_QUERY_SEVERAL_SPECIFIC_TYPE = "select type_name from $1 LIMIT ?, ?"; + /** + * sql for query evidence by hash. + */ + public static final String SQL_QUERY_EVIDENCE_BY_HASH = "select hash,signers,signatures,logs,updated,revoked,extra_key,extra_data,group_id from $1 where hash =?"; + /** + * sql for query evidence by extra_key. + */ + public static final String SQL_QUERY_EVIDENCE_BY_EXTRAKEY = "select hash,signers,signatures,logs,updated,revoked,extra_key,extra_data,group_id from $1 where extra_key =?"; + /** + * sql for insert evidence. + */ + public static final String SQL_SAVE_EVIDENCE_BY_HASH = "insert into $1 (hash,signers,signatures,logs,updated,revoked,group_id) values(?,?,?,?,?,?,?)"; + /** + * sql for insert evidence. + */ + public static final String SQL_SAVE_EVIDENCE_EXTRAKEY = "insert into $1 (hash,signers,signatures,logs,updated,revoked,extra_key,group_id) values(?,?,?,?,?,?,?,?)"; + /** + * sql for update evidence. + */ + public static final String SQL_UPDATE_EVIDENCE = "update $1 set signers = ?, signatures = ?, logs = ?, updated = ?, revoked = ?, extra_key = ? where hash = ?"; + + private static final Logger logger = LoggerFactory.getLogger(SqlExecutor.class); + /** + * 批次提交个数. + */ + private static final int BATCH_COMMIT_COUNT = 200; + /** + * tableDomain 与 tableName的映射. + */ + private static final Map TABLE_CACHE = new ConcurrentHashMap(); + + /** + * the sql domain. + */ + private SqlDomain sqlDomain; + + /** + * 根据domain创建SQL执行器. + * + * @param sqlDomain the Sqldomain + */ + public SqlExecutor(SqlDomain sqlDomain) { + if (sqlDomain != null) { + this.sqlDomain = sqlDomain; + } else { + this.sqlDomain = new SqlDomain(); + } + } + + /** + * 根据数据源名称构建SQL执行器. + * + * @param dataSourceName 数据源名称 + */ + public SqlExecutor(String dataSourceName) { + this.sqlDomain = new SqlDomain(); + this.sqlDomain.setBaseDomain(dataSourceName); + } + + /** + * 查询操作. + * + * @param sql 需要被执行的SQL语句 + * @param data 占位符所需要的数据 + * @return 返回查询出来的单个数据 + */ + public ResponseData> executeQuery(String sql, Object... data) { + ResponseData> result = new ResponseData>(); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = ConnectionPool.getConnection(sqlDomain.getBaseDomain()); + if (conn == null) { + return + new ResponseData>( + null, + ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR + ); + } + + ps = conn.prepareStatement(buildExecuteSql(sql, conn)); + for (int i = 0; i < data.length; i++) { + ps.setObject(i + 1, data[i]); + } + + rs = ps.executeQuery(); + Map dataMap = null; + if (rs.next()) { + dataMap = new HashMap(); + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String columnLabel = metaData.getColumnLabel(i); + int type = metaData.getColumnType(i); + if (type == Types.TIMESTAMP) { + Timestamp timestamp = rs.getTimestamp(columnLabel); + if (timestamp != null) { + dataMap.put(columnLabel, String.valueOf(timestamp.getTime())); + } + } else { + dataMap.put(columnLabel, rs.getString(columnLabel)); + } + } + } + rs.close(); + ps.close(); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(dataMap); + } catch (SQLException e) { + logger.error("Query data from {{}} with exception", sqlDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } finally { + ConnectionPool.close(conn, ps, rs); + } + return result; + } + + /** + * 增删改的通用执行方法. + * + * @param sql 需要被执行的SQL语句 + * @param data 占位符所需要的数据 + * @return 返回执行受影响的行数 + */ + public ResponseData execute(String sql, Object... data) { + ResponseData result = new ResponseData(); + Connection conn = null; + PreparedStatement ps = null; + try { + conn = ConnectionPool.getConnection(sqlDomain.getBaseDomain()); + if (conn == null) { + return + new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR + ); + } + ps = conn.prepareStatement(buildExecuteSql(sql, conn)); + for (int i = 0; data != null && i < data.length; i++) { + if (data[i] instanceof Date) { + Date date = (Date) data[i]; + ps.setTimestamp(i + 1, new Timestamp(date.getTime())); + continue; + } + ps.setObject(i + 1, data[i]); + } + int rs = ps.executeUpdate(); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(rs); + } catch (SQLException e) { + logger.error("Update data into {{}} with exception", sqlDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.SQL_EXECUTE_FAILED_STATUS); + } finally { + ConnectionPool.close(conn, ps); + } + return result; + } + + /** + * 查询操作. + * + * @param sql 需要被执行的SQL语句 + * @param data 占位符所需要的数据 + * @return 返回查询出来的多行数据,每行仅查询一列,仅用于按序号查询多个weid + */ + public ResponseData> executeQueryLines(String sql, Object... data) { + ResponseData> result = new ResponseData>(); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = ConnectionPool.getConnection(sqlDomain.getBaseDomain()); + if (conn == null) { + return + new ResponseData>( + null, + ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR + ); + } + + ps = conn.prepareStatement(buildExecuteSql(sql, conn)); + for (int i = 0; i < data.length; i++) { + ps.setObject(i + 1, data[i]); + } + + rs = ps.executeQuery(); + List dataList = new ArrayList<>(); + while (rs.next()) { + ResultSetMetaData metaData = rs.getMetaData(); + String columnLabel = metaData.getColumnLabel(1); + dataList.add(rs.getString(columnLabel)); + /*int type = metaData.getColumnType(i); + if (type == Types.TIMESTAMP) { + Timestamp timestamp = rs.getTimestamp(columnLabel); + if (timestamp != null) { + dataMap.put(columnLabel, String.valueOf(timestamp.getTime())); + } + } else { + dataMap.put(columnLabel, rs.getString(columnLabel)); + }*/ + } + rs.close(); + ps.close(); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(dataList); + } catch (SQLException e) { + logger.error("Query data from {{}} with exception", sqlDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } finally { + ConnectionPool.close(conn, ps, rs); + } + return result; + } + + /** + * 查询操作. + * + * @param sql 需要被执行的SQL语句 + * @return 返回查询数据总行数 + */ + public ResponseData executeQueryAmounts(String sql) { + ResponseData result = new ResponseData(); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = ConnectionPool.getConnection(sqlDomain.getBaseDomain()); + if (conn == null) { + return + new ResponseData( + 0, + ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR + ); + } + ps = conn.prepareStatement(buildExecuteSql(sql, conn)); + rs = ps.executeQuery(); + int rowCount = 0; + if(rs.next()) { + rowCount = rs.getInt("totalCount"); + } + rs.close(); + ps.close(); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(rowCount); + } catch (SQLException e) { + logger.error("Query data from {{}} with exception", sqlDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } finally { + ConnectionPool.close(conn, ps, rs); + } + return result; + } + + /** + * 批量新增的通用语句. + * + * @param sql 需要被执行的数据 + * @param dataList 占位符所需要的数据 + * @return 返回受影响的行数 + */ + public ResponseData batchAdd(String sql, List> dataList) { + ResponseData result = new ResponseData(); + Connection conn = null; + PreparedStatement psts = null; + try { + List values = dataList.get(dataList.size() - 1); + for (List list : dataList) { + if (CollectionUtils.isEmpty(list) || list.size() != values.size()) { + return + new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_BATCH_ADD_DATA_MISMATCH + ); + } + } + conn = ConnectionPool.getConnection(sqlDomain.getBaseDomain()); + if (conn == null) { + return + new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR + ); + } + conn.setAutoCommit(false); + psts = conn.prepareStatement(buildExecuteSql(sql, conn)); + int count = 0; + for (int i = 0; i < values.size(); i++) { + for (int j = 0; j < dataList.size(); j++) { + psts.setObject(j + 1, dataList.get(j).get(i)); + } + psts.addBatch(); + // 每500提交一次 + if (i % BATCH_COMMIT_COUNT == 0) { + int[] counts = psts.executeBatch(); + conn.commit(); + psts.clearBatch(); + for (int j : counts) { + count += j; + } + } + } + int[] counts = psts.executeBatch(); + conn.commit(); + psts.clearBatch(); + for (int j : counts) { + count += j; + } + result.setResult(count); + } catch (SQLException e) { + logger.error("Batch add data to {{}} with exception", sqlDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.SQL_EXECUTE_FAILED_STATUS); + } finally { + ConnectionPool.close(conn, psts); + } + return result; + } + + /** + * 检查表是否存在,如果不存在则创建表. + * + * @param checkTableSql 检查表是存在的sql语句 + * @param createTableSql 创建表的sql语句 + */ + public void resolveTableDomain(String checkTableSql, String createTableSql) { + synchronized (TABLE_CACHE) { + String tableName = TABLE_CACHE.get(sqlDomain.getKey()); + //说明本地没有此tableDomain + if (StringUtils.isBlank(tableName)) { + if (this.initLocalTable(checkTableSql)) { + return; + } + this.createTable(createTableSql); + if (!this.initLocalTable(checkTableSql)) { + logger.error( + "[resolveTableDomain] the domain {{}:{}} is invalid.", + sqlDomain.getKey(), + sqlDomain.getValue() + ); + throw new WeIdBaseException(ErrorCode.PRESISTENCE_DOMAIN_INVALID); + } + } + } + } + + // 检查表是否存在,如果存在则返回表名 + private Map checkTable(String checkTableSql) { + //检查数据库中是否存在此表 + ResponseData> resultRes = this.executeQuery(checkTableSql); + if (resultRes.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[initLocalTable] execute query table name fail, code:{}, message:{}.", + resultRes.getErrorCode(), + resultRes.getErrorMessage() + ); + throw new WeIdBaseException( + ErrorCode.getTypeByErrorCode(resultRes.getErrorCode())); + } + Map result = resultRes.getResult(); + //如果数据库中存在此表 + if (result != null) { + return result; + } + return null; + } + + private boolean initLocalTable(String checkTableSql) { + Map result = checkTable(checkTableSql); + String tableName = sqlDomain.getTableName(); + //如果数据库中存在此表 + if (result != null + && tableName.equalsIgnoreCase(result.get(DataDriverConstant.SQL_COLUMN_DATA))) { + //本地缓存记录此表 + TABLE_CACHE.put(sqlDomain.getKey(), tableName); + logger.info( + "[initLocalTable] the domain {{}:{}} is init success.", + sqlDomain.getKey(), + sqlDomain.getValue() + ); + return true; + } + return false; + } + + private void createTable(String createTableSql) { + //动态创建此表 + ResponseData createRes = this.execute(createTableSql); + //创建失败 + if (createRes.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[createTable] execute create table fail, code:{}, message:{}.", + createRes.getErrorCode(), + createRes.getErrorMessage() + ); + throw new WeIdBaseException( + ErrorCode.getTypeByErrorCode(createRes.getErrorCode())); + } + } + + /** + * 此方法用于非Domain体系创建自定义表使用. + * + * @param checkTableSql 检查表是否存在的SQL语句 + * @param createTableSql 创建表的SQL语句 + * @return 返回表是否创建成功 + */ + public boolean createTable(String checkTableSql, String createTableSql) { + // 先检查表 + Map result = checkTable(checkTableSql); + if (result == null) { + // 说明表不存在,创建表 + this.createTable(createTableSql); + // 再确认一次是否存在 + result = checkTable(checkTableSql); + if (result == null) { + return false; + } + } + return true; + } + + private String buildExecuteSql(String exeSql, Connection conn) throws SQLException { + exeSql = exeSql.replace(TABLE_CHAR, sqlDomain.getTableName()); + exeSql = exeSql.replace(DATABASE_CHAR, conn.getCatalog()); + return exeSql; + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/mysql/driver/MysqlDriver.java b/src/main/java/com/webank/weid/suite/persistence/mysql/driver/MysqlDriver.java new file mode 100644 index 00000000..63d0e568 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/mysql/driver/MysqlDriver.java @@ -0,0 +1,1412 @@ + + +package com.webank.weid.suite.persistence.mysql.driver; + +import com.webank.weid.blockchain.protocol.base.AuthorityIssuer; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.WeIdDocumentMetadata; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.contract.deploy.AddressProcess; +import com.webank.weid.exception.DatabaseException; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.AuthenticationProperty; +import com.webank.weid.blockchain.protocol.base.WeIdDocument; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.local.CptServiceLocal; +import com.webank.weid.suite.persistence.*; +import com.webank.weid.suite.persistence.mysql.SqlDomain; +import com.webank.weid.suite.persistence.mysql.SqlExecutor; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.PropertyUtils; +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.*; + +/** + * mysql operations. + * + * @author tonychen 2019年3月18日 + */ +public class MysqlDriver implements Persistence { + + private static final Logger logger = LoggerFactory.getLogger( + MysqlDriver.class); + + private static final String CHECK_TABLE_SQL = + "SELECT table_name " + + DataDriverConstant.SQL_COLUMN_DATA + + " FROM information_schema.TABLES " + + " WHERE upper(table_name) = upper('$1')" + + " and upper(table_schema) = upper('$2')"; + + private static final String CREATE_TABLE_SQL = + "CREATE TABLE `$1` (" + + "`id` varchar(128) NOT NULL COMMENT 'primary key'," + + "`data` blob DEFAULT NULL COMMENT 'the add data', " + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`protocol` varchar(32) DEFAULT NULL COMMENT 'protocol', " + + "`expire` datetime DEFAULT NULL COMMENT 'the expire time', " + + "`version` varchar(10) DEFAULT NULL COMMENT 'the data version', " + + "`ext1` int DEFAULT NULL COMMENT 'extend field1', " + + "`ext2` int DEFAULT NULL COMMENT 'extend field2', " + + "`ext3` varchar(500) DEFAULT NULL COMMENT 'extend field3', " + + "`ext4` varchar(500) DEFAULT NULL COMMENT 'extend field4', " + + "PRIMARY KEY (`id`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the data table'"; + + private static final String CREATE_TABLE_WEID_DOCUMENT_SQL = + "CREATE TABLE `$1` (" + + "`weid` varchar(100) NOT NULL UNIQUE COMMENT 'weid'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`version` int DEFAULT NULL COMMENT 'the document version', " + + "`deactivated` int DEFAULT NULL COMMENT 'deactivated', " + + "`document_schema` blob DEFAULT NULL COMMENT 'json schema of document', " + + "PRIMARY KEY (`weid`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the weid document table'"; + + private static final String CREATE_TABLE_CPT_SQL = + "CREATE TABLE `$1` (" + + "`cpt_id` int NOT NULL UNIQUE COMMENT 'cpt id'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`cpt_version` int DEFAULT NULL COMMENT 'the cpt version', " + + "`publisher` varchar(60) DEFAULT NULL COMMENT 'publisher', " + + "`description` varchar(1000) DEFAULT NULL COMMENT 'description of cpt', " + + "`cpt_schema` blob DEFAULT NULL COMMENT 'json schema of cpt', " + + "`cpt_signature` varchar(500) DEFAULT NULL COMMENT 'signature of cpt', " + + "`credential_publicKey` varchar(60) DEFAULT NULL COMMENT 'publicKey of credential template', " + + "`credential_proof` varchar(1000) DEFAULT NULL COMMENT 'proof of credential template', " + + "`claim_policies` varchar(1000) DEFAULT NULL COMMENT 'policy id list', " + + "PRIMARY KEY (`cpt_id`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the cpt table'"; + + private static final String CREATE_TABLE_POLICY_SQL = + "CREATE TABLE `$1` (" + + "`policy_id` int NOT NULL UNIQUE COMMENT 'policy id'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`policy_version` int DEFAULT NULL COMMENT 'the policy version', " + + "`publisher` varchar(60) DEFAULT NULL COMMENT 'publisher', " + + "`description` varchar(1000) DEFAULT NULL COMMENT 'description of policy', " + + "`policy_schema` blob DEFAULT NULL COMMENT 'json schema of policy', " + + "`policy_signature` varchar(500) DEFAULT NULL COMMENT 'signature of policy', " + + "`credential_publicKey` varchar(60) DEFAULT NULL COMMENT 'publicKey of credential template', " + + "`credential_proof` varchar(1000) DEFAULT NULL COMMENT 'proof of credential template', " + + "`claim_policies` varchar(1000) DEFAULT NULL COMMENT 'policy id list', " + + "PRIMARY KEY (`policy_id`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the policy table'"; + + private static final String CREATE_TABLE_PRESENTATION_SQL = + "CREATE TABLE `$1` (" + + "`presentation_id` int NOT NULL UNIQUE COMMENT 'presentation id'," + + "`creator` varchar(60) DEFAULT NULL COMMENT 'creator', " + + "`claim_policies` varchar(1000) DEFAULT NULL COMMENT 'policy id list', " + + "PRIMARY KEY (`presentation_id`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the presentation table'"; + + private static final String CREATE_TABLE_ROLE_SQL = + "CREATE TABLE `$1` (" + + "`weid` varchar(100) NOT NULL UNIQUE COMMENT 'weid'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`authority_role` int DEFAULT NULL COMMENT 'the authority role', " + + "`committee_role` int DEFAULT NULL COMMENT 'the committee role', " + + "`admin_role` int DEFAULT NULL COMMENT 'the admin role', " + + "PRIMARY KEY (`weid`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the role table'"; + + private static final String CREATE_TABLE_AUTHORITY_ISSUER_SQL = + "CREATE TABLE `$1` (" + + "`weid` varchar(100) NOT NULL UNIQUE COMMENT 'weid'," + + "`name` varchar(60) UNIQUE DEFAULT NULL COMMENT 'name'," + + "`description` varchar(1000) DEFAULT NULL COMMENT 'desc'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`recognize` int DEFAULT NULL COMMENT 'is recognized', " + + "`acc_value` varchar(1000) DEFAULT NULL COMMENT 'the accValue', " + + "`extra_str` blob DEFAULT NULL COMMENT 'the extraStr', " + + "`extra_int` blob DEFAULT NULL COMMENT 'the extraInt', " + + "PRIMARY KEY (`weid`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the authority issuer table'"; + + private static final String CREATE_TABLE_SPECIFIC_ISSUER_SQL = + "CREATE TABLE `$1` (" + + "`type_name` varchar(60) NOT NULL UNIQUE COMMENT 'specific issuer type name'," + + "`fellow` blob DEFAULT NULL COMMENT 'fellow addresses'," + + "`created` datetime DEFAULT NULL COMMENT 'created', " + + "`updated` datetime DEFAULT NULL COMMENT 'updated', " + + "`owner` varchar(60) DEFAULT NULL COMMENT 'owner'," + + "PRIMARY KEY (`type_name`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the specific issuer table'"; + + private static final String CREATE_TABLE_EVIDENCE_SQL = + "CREATE TABLE `$1` (" + + "`hash` varchar(100) NOT NULL UNIQUE COMMENT 'hash of evidence'," + + "`signers` blob DEFAULT NULL COMMENT 'signers'," + + "`signatures` blob DEFAULT NULL COMMENT 'signatures', " + + "`logs` blob DEFAULT NULL COMMENT 'logs', " + + "`updated` blob DEFAULT NULL COMMENT 'updated', " + + "`revoked` blob DEFAULT NULL COMMENT 'revoked'," + + "`extra_key` varchar(100) DEFAULT NULL COMMENT 'extraKey of evidence'," + + "`extra_data` blob DEFAULT NULL COMMENT 'extraData of evidence'," + + "`group_id` blob NOT NULL COMMENT 'group_id of evidence'," + + "PRIMARY KEY (`hash`) " + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='the evidence table'"; + + private static final Integer FAILED_STATUS = DataDriverConstant.SQL_EXECUTE_FAILED_STATUS; + + private static final ErrorCode KEY_INVALID = ErrorCode.PRESISTENCE_DATA_KEY_INVALID; + + private static Boolean isinit = false; + + private static int CPT_DEFAULT_VERSION = 1; + + /** + * the Constructor and init all domain. + */ + public MysqlDriver() { + if (!isinit) { + synchronized (MysqlDriver.class) { + if (!isinit) { + initDomain(); + isinit = true; + } + } + } + } + + @Override + public ResponseData get(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[mysql->get] the id of the data is empty."); + return new ResponseData(StringUtils.EMPTY, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + ResponseData result = new ResponseData(); + result.setResult(StringUtils.EMPTY); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY, dataKey); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + DefaultValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), DefaultValue.class); + if (tableData.getExpire() != null && tableData.getExpire().before(new Date())) { + logger.error("[mysql->get] the data is expire."); + return new ResponseData(StringUtils.EMPTY, + ErrorCode.PERSISTENCE_DATA_EXPIRE); + } + if (StringUtils.isNotBlank(tableData.getData())) { + result.setResult(tableData.getData()); + } + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->get] get the data error.", e); + return new ResponseData(StringUtils.EMPTY, e.getErrorCode()); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.connectivity.driver.DBDriver#add(java.lang.String, java.lang.String) + */ + @Override + public ResponseData add(String domain, String id, String data) { + + if (StringUtils.isEmpty(id)) { + logger.error("[mysql->add] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {dataKey, data, sqlDomain.getExpire(), now, now}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->add] add the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + + /* (non-Javadoc) + * @see com.webank.weid.connectivity.driver.DBDriver#batchAdd(java.util.List, java.util.List) + */ + @Override + public ResponseData batchAdd(String domain, Map keyValueList) { + try { + List idHashList = new ArrayList<>(); + List dataList = new ArrayList<>(); + Iterator iterator = keyValueList.keySet().iterator(); + while (iterator.hasNext()) { + String id = iterator.next(); + String data = keyValueList.get(id); + if (StringUtils.isEmpty(id)) { + logger.error("[mysql->batchAdd] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + idHashList.add(DataToolUtils.hash(id)); + dataList.add(data); + } + SqlDomain sqlDomain = new SqlDomain(domain); + List> dataLists = new ArrayList>(); + dataLists.add(idHashList); + dataLists.add(Arrays.asList(dataList.toArray())); + dataLists.add(fixedListWithDefault(idHashList.size(), sqlDomain.getExpire())); + + //处理创建时间和更新时间 + List nowList = fixedListWithDefault(idHashList.size(), sqlDomain.getNow()); + dataLists.add(nowList); + dataLists.add(nowList); + return new SqlExecutor(sqlDomain).batchAdd(SqlExecutor.SQL_SAVE, dataLists); + } catch (WeIdBaseException e) { + logger.error("[mysql->batchAdd] batchAdd the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + private List fixedListWithDefault(int size, Object obj) { + Object[] dates = new Object[size]; + Arrays.fill(dates, obj); + List list = new ArrayList<>(); + list.addAll(Arrays.asList(dates)); + return list; + } + + /* (non-Javadoc) + * @see com.webank.weid.connectivity.driver.DBDriver#delete(java.lang.String) + */ + @Override + public ResponseData delete(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[mysql->delete] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_DELETE, dataKey); + } catch (WeIdBaseException e) { + logger.error("[mysql->delete] delete the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + /* (non-Javadoc) + * @see com.webank.weid.connectivity.driver.DBDriver#update(java.lang.String, java.lang.String) + */ + @Override + public ResponseData update(String domain, String id, String data) { + + if (StringUtils.isEmpty(id)) { + logger.error("[mysql->update] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + Date date = new Date(); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Object[] datas = {date, data, sqlDomain.getExpire(), dataKey}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->update] update the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + /** + * 初始化domain. + */ + private void initDomain() { + Set domainKeySet = analyzeDomainValue(); + Set localKeySet = analyzeLocalValue(); + for (String domainKey : domainKeySet) { + SqlExecutor sqlExecutor = new SqlExecutor(new SqlDomain(domainKey)); + sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_SQL); + } + String type = PropertyUtils.getProperty("deploy.style"); + if (type.equals("database")) { + // 初始化表 + for (String localKey : localKeySet) { + SqlExecutor sqlExecutor = new SqlExecutor(new SqlDomain(localKey)); + switch (localKey) { + case "local.weIdDocument" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_WEID_DOCUMENT_SQL); + case "local.cpt" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_CPT_SQL); + case "local.policy" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_POLICY_SQL); + case "local.presentation" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_PRESENTATION_SQL); + case "local.role" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_ROLE_SQL); + case "local.authorityIssuer" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_AUTHORITY_ISSUER_SQL); + case "local.specificIssuer" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_SPECIFIC_ISSUER_SQL); + case "local.evidence" : sqlExecutor.resolveTableDomain(CHECK_TABLE_SQL, CREATE_TABLE_EVIDENCE_SQL); + } + } + // 初始化管理员权限 + String privateKey = getAddressFromFile("private_key"); + RoleValue result = getRole(DataDriverConstant.LOCAL_ROLE, WeIdUtils.getWeIdFromPrivateKey(privateKey)).getResult(); + if(result == null) { + ResponseData resp = addRole(DataDriverConstant.LOCAL_ROLE, WeIdUtils.getWeIdFromPrivateKey(privateKey), 7); + if (resp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[initDomain] save admin role to db failed."); + throw new DatabaseException("database error!"); + } + } + } + } + + protected static String getAddressFromFile( + String fileName) { + + BufferedReader br = null; + try { + File file = new File(fileName); + if (file.exists()) { + br = new BufferedReader( + new InputStreamReader(new FileInputStream(file)) + ); + String address = br.readLine(); + return address; + } + } catch (IOException e) { + logger.error("writer file exception", e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + logger.error("io close exception", e); + } + } + } + logger.error("getAddressFromFile() the {} does not exists.", fileName); + return StringUtils.EMPTY; + } + + /** + * 分析配置中的domain配置, 并且获取对应的配置项key. + * + * @return 返回配置值 + */ + private Set analyzeDomainValue() { + Set keySet = PropertyUtils.getAllPropertyKey(); + Set domainKeySet = new HashSet<>(); + for (Object object : keySet) { + String key = String.valueOf(object); + if (key.indexOf(SqlDomain.KEY_SPLIT_CHAR) == key.lastIndexOf(SqlDomain.KEY_SPLIT_CHAR) + && key.startsWith(SqlDomain.DOMAIN_PREFIX)) { + domainKeySet.add(key); + } + } + return domainKeySet; + } + + /** + * 分析配置中的local配置, 并且获取对应的配置项key. + * + * @return 返回配置值 + */ + private Set analyzeLocalValue() { + Set keySet = PropertyUtils.getAllPropertyKey(); + Set localKeySet = new HashSet<>(); + for (Object object : keySet) { + String key = String.valueOf(object); + if (key.indexOf(SqlDomain.KEY_SPLIT_CHAR) == key.lastIndexOf(SqlDomain.KEY_SPLIT_CHAR) + && key.startsWith(SqlDomain.LOCAL_PREFIX)) { + localKeySet.add(key); + } + } + return localKeySet; + } + + /* (non-Javadoc) + * @see com.webank.weid.suite.persistence.Persistence#addOrUpdate(java.lang.String, + * java.lang.String, java.lang.String) + */ + @Override + public ResponseData addOrUpdate(String domain, String id, String data) { + ResponseData getRes = this.get(domain, id); + //如果查询数据存在,或者失效 则进行更新 否则进行新增 + if ((StringUtils.isNotBlank(getRes.getResult()) + && getRes.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode()) + || getRes.getErrorCode().intValue() == ErrorCode.PERSISTENCE_DATA_EXPIRE.getCode()) { + return this.update(domain, id, data); + } + return this.add(domain, id, data); + } + + + /* (non-Javadoc) + * @see com.webank.weid.suite.persistence.Persistence#addTransaction( + * com.webank.weid.protocol.request.TransactionArgs) + */ + @Override + public ResponseData addTransaction(TransactionArgs transactionArgs) { + + if (StringUtils.isEmpty(transactionArgs.getRequestId())) { + logger.error("[mysql->add] the id of the data is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(DataDriverConstant.DOMAIN_DEFAULT_INFO); + Object[] datas = { + transactionArgs.getRequestId(), + transactionArgs.getMethod(), + transactionArgs.getArgs(), + transactionArgs.getTimeStamp(), + transactionArgs.getExtra(), + transactionArgs.getBatch() + }; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_TRANSACTION, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->add] add the data error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addWeId(String domain, String weId, String documentSchema) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->addWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {weId, now, now, 1, 0, documentSchema}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_WEID, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->addWeId] addWeId error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateWeId(String domain, String weId, String documentSchema) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->updateWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + Date date = new Date(); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_WEID, weId); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[mysql->updateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + int version = tableData.getVersion(); + version++; + Object[] datas = {date, version, tableData.getDeactivated(), documentSchema, weId}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_WEID, datas); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateWeId] update the weid error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdDocument(String domain, String weId) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->getWeIdDocument] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + //String dataKey = DataToolUtils.hash(weId); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_WEID, weId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + return new ResponseData<>(WeIdDocument.fromJson(tableData.getDocument_schema()), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } catch (WeIdBaseException e) { + logger.error("[mysql->getWeIdDocument] get the weIdDocument error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getMeta(String domain, String weId) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->getMeta] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + //String dataKey = DataToolUtils.hash(weId); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_WEID, weId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + WeIdDocumentMetadata weIdDocumentMetadata = new WeIdDocumentMetadata(); + weIdDocumentMetadata.setCreated(tableData.getCreated().getTime()); + weIdDocumentMetadata.setUpdated(tableData.getUpdated().getTime()); + weIdDocumentMetadata.setVersionId(tableData.getVersion()); + weIdDocumentMetadata.setDeactivated(tableData.getDeactivated() == 1); + return new ResponseData<>(weIdDocumentMetadata, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getMeta] getMeta error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData deactivateWeId(String domain, String weId, Boolean state) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->deactivateWeId] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(weId); + Date date = new Date(); + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_WEID, dataKey); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[mysql->deactivateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + Object[] datas = {date, tableData.getVersion(), state ? 1:0, tableData.getDocument_schema(), weId}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_WEID, datas); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->deactivateWeId] deactivate the weId error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData> getWeIdList(String domain, Integer first, Integer last) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Object[] datas = {first, last - first + 1}; + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQueryLines(SqlExecutor.SQL_QUERY_SEVERAL_WEID, datas); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getWeIdList] get the data error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_LINE); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getWeIdCount] get the data error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData getCpt(String domain, int cptId) { + + if (cptId<=0) { + logger.error("[mysql->getCpt] the cptId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_CPT, cptId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + CptValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), CptValue.class); + if (StringUtils.isNotBlank(tableData.getCpt_schema())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getCpt] getCpt error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData addCpt(String domain, int cptId, String publisher, String description, String cptSchema, String cptSignature) { + + if (cptId<=0) { + logger.error("[mysql->addCpt] the cptId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {cptId, now, now, CPT_DEFAULT_VERSION, publisher, description, cptSchema, cptSignature}; + ResponseData result = new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_CPT, datas); + if (result.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addCpt] add Cpt to db failed."); + throw new DatabaseException("database error!"); + } + CptBaseInfo cptBaseInfo = new CptBaseInfo(); + cptBaseInfo.setCptId(cptId); + cptBaseInfo.setCptVersion(CPT_DEFAULT_VERSION); + return new ResponseData<>(cptBaseInfo, ErrorCode.SUCCESS); + } catch (WeIdBaseException e) { + logger.error("[mysql->addCpt] addWeId error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData updateCpt(String domain, int cptId, int cptVersion, String publisher, String description, String cptSchema, String cptSignature) { + + if (cptId<=0) { + logger.error("[mysql->updateCpt] the cptId is invalid."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {now, cptVersion, publisher, description, cptSchema, cptSignature, cptId}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_CPT, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateCpt] updateCpt error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData> getCptIdList(String domain, Integer first, Integer last) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Object[] datas = {first, last - first}; + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQueryLines(SqlExecutor.SQL_QUERY_SEVERAL_CPT, datas); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + List cptList = new ArrayList<>(); + for(int i=0; i(cptList, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getCptIdList] get the CptIdList error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getCptCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_LINE); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getCptCount] get the count of cpt error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData> getPolicyIdList(String domain, Integer first, Integer last) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Object[] datas = {first, last - first}; + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQueryLines(SqlExecutor.SQL_QUERY_SEVERAL_POLICY, datas); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + List cptList = new ArrayList<>(); + for(int i=0; i(cptList, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getPolicyIdList] get the PolicyIdList error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getPolicyCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_LINE); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getPolicyCount] get the count of policy error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData updateCredentialTemplate(String domain, int cptId, String credentialPublicKey, String credentialProof) { + + if (cptId<=0) { + logger.error("[mysql->putCredentialTemplate] the cptId is invalid."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {credentialPublicKey, credentialProof, cptId}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_CREDENTIAL_TEMPLATE, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->putCredentialTemplate] updateCpt error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateCptClaimPolicies(String domain, int cptId, String policies) { + + if (cptId<=0) { + logger.error("[mysql->updateCptClaimPolicies] the cptId is invalid."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {policies, cptId}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_CLAIM_POLICIES, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateCptClaimPolicies] updateCptClaimPolicies error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addPolicy(String domain, int policyId, String publisher, String description, String cptSchema, String cptSignature) { + + if (policyId<=0) { + logger.error("[mysql->addPolicy] the policyId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {policyId, now, now, CPT_DEFAULT_VERSION, publisher, description, cptSchema, cptSignature}; + ResponseData result = new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_POLICY, datas); + if (result.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addPolicy] add policy to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(result.getResult(), ErrorCode.SUCCESS); + } catch (WeIdBaseException e) { + logger.error("[mysql->addPolicy] addPolicy error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getPolicy(String domain, int policyId) { + //Policy和cpt的表一样,所以可以复用CptValue + if (policyId<=0) { + logger.error("[mysql->getCpt] the cptId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_POLICY, policyId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + PolicyValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), PolicyValue.class); + if (StringUtils.isNotBlank(tableData.getPolicy_schema())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.CPT_NOT_EXISTS); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getPolicy] getCpt error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData addPresentation(String domain, int presentationId, String creator, String policies) { + + if (presentationId<=0) { + logger.error("[mysql->addPresentation] the presentationId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {presentationId, creator, policies}; + ResponseData result = new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_PRESENTATION, datas); + if (result.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + logger.error("[addPresentation] add presentation to db failed."); + throw new DatabaseException("database error!"); + } + return new ResponseData<>(result.getResult(), ErrorCode.SUCCESS); + } catch (WeIdBaseException e) { + logger.error("[mysql->addPresentation] addPresentation error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getPresentation(String domain, int presentationId) { + if (presentationId<=0) { + logger.error("[mysql->getPresentation] the presentationId is invalid."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_PRESENTATION, presentationId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + PresentationValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), PresentationValue.class); + if (StringUtils.isNotBlank(tableData.getClaim_policies())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.PRESENTATION_POLICY_INVALID); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getPresentation] getPresentation error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getAuthorityIssuerByWeId(String domain, String weId) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->getAuthorityIssuerByWeId] the weId is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_AUTHORITY_ISSUER_BY_ADDRESS, weId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + AuthorityIssuerInfo tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), AuthorityIssuerInfo.class); + if (StringUtils.isNotBlank(tableData.getName())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getAuthorityIssuerByWeId] getAuthorityIssuerByWeId error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getAuthorityIssuerByName(String domain, String name) { + + if (StringUtils.isEmpty(name)) { + logger.error("[mysql->getAuthorityIssuerByName] the name is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_AUTHORITY_ISSUER_BY_NAME, name); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + AuthorityIssuerInfo tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), AuthorityIssuerInfo.class); + if (StringUtils.isNotBlank(tableData.getWeid())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getAuthorityIssuerByName] getAuthorityIssuerByName error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData addAuthorityIssuer(String domain, String weId, String name, String desc, String accValue, String extraStr, String extraInt) { + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->addAuthorityIssuer] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {weId, name, desc, now, now, 0, accValue, extraStr, extraInt}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_AUTHORITY_ISSUER, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->addAuthorityIssuer] addAuthorityIssuer error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData removeAuthorityIssuer(String domain, String weId) { + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->removeAuthorityIssuer] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_DELETE_AUTHORITY_ISSUER, weId); + } catch (WeIdBaseException e) { + logger.error("[mysql->removeAuthorityIssuer] addAuthorityIssuer error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateAuthorityIssuer(String domain, String weId, Integer recognize) { + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->updateAuthorityIssuer] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_AUTHORITY_ISSUER_BY_ADDRESS, weId); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + AuthorityIssuerInfo tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), AuthorityIssuerInfo.class); + + if (StringUtils.isNotBlank(tableData.getName())) { + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_AUTHORITY_ISSUER, new Object[]{now, recognize, weId}); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateAuthorityIssuer] update the AuthorityIssuer error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getAuthorityIssuerCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_LINE); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getAuthorityIssuerCount] get the count of AuthorityIssuer error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData getRecognizedIssuerCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_RECOGNIZED_ISSUER); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getRecognizedIssuerCount] get the count of recognized authority issuer error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData getRole(String domain, String weId) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->getRole] the weId is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_ROLE, weId); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + RoleValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), RoleValue.class); + if (tableData.getUpdated().before(now)) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getRole] getRole error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + //1 as authority_role, 2 as committee_role, 3 as authority_role & committee_role, 4 as admin_role, 5 as authority_role & admin_role, 6 as committee_role & admin_role, 7 as all role + @Override + public ResponseData addRole(String domain, String weId, Integer roleValue) { + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->addRole] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + if (roleValue > 7 || roleValue < 1) { + logger.error("[mysql->addRole] the roleValue is not between 1 and 7."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + switch (roleValue) { + case 1 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 1, 0, 0}); + case 2 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 0, 1, 0}); + case 3 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 1, 1, 0}); + case 4 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 0, 0, 1}); + case 5 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 1, 0, 1}); + case 6 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 0, 1, 1}); + case 7 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 1, 1, 1}); + default: return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_ROLE, new Object[]{weId, now, now, 0, 0, 0}); + } + } catch (WeIdBaseException e) { + logger.error("[mysql->addRole] addRole error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateRole(String domain, String weId, Integer roleValue) { + if (StringUtils.isEmpty(weId)) { + logger.error("[mysql->updateRole] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + if (roleValue > 7 || roleValue < 1) { + logger.error("[mysql->updateRole] the roleValue is not between 1 and 7."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_ROLE, weId); + if (response.getErrorCode().intValue() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + RoleValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), RoleValue.class); + + if (tableData.getUpdated().before(now)) { + switch (roleValue) { + case 1 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 1, 0, 0, weId}); + case 2 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 0, 1, 0, weId}); + case 3 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 1, 1, 0, weId}); + case 4 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 0, 0, 1, weId}); + case 5 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 1, 0, 1, weId}); + case 6 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 0, 1, 1, weId}); + case 7 : return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 1, 1, 1, weId}); + default: return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_ROLE, new Object[]{now, 0, 0, 0, 0, weId}); + } + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateRole] update the weid error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addSpecificType(String domain, String typeName, String owner) { + if (StringUtils.isEmpty(typeName)) { + logger.error("[mysql->addSpecificType] the typeName is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {typeName, now, now, owner}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_SPECIFIC_TYPE, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->addSpecificType] addSpecificType error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData removeSpecificType(String domain, String typeName) { + if (StringUtils.isEmpty(typeName)) { + logger.error("[mysql->removeSpecificType] the weId is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_DELETE_SPECIFIC_TYPE, typeName); + } catch (WeIdBaseException e) { + logger.error("[mysql->removeSpecificType] removeSpecificType error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getSpecificType(String domain, String typeName) { + + if (StringUtils.isEmpty(typeName)) { + logger.error("[mysql->getSpecificType] the typeName is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_SPECIFIC_TYPE, typeName); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + SpecificTypeValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), SpecificTypeValue.class); + if (tableData.getUpdated().before(now)) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getSpecificType] getSpecificType error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData updateSpecificTypeFellow(String domain, String typeName, String fellow) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {fellow, typeName}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_SPECIFIC_TYPE_FELLOW, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->updateSpecificTypeFellow] updateSpecificTypeFellow error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getIssuerTypeCount(String domain) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData response = new SqlExecutor(sqlDomain) + .executeQueryAmounts(SqlExecutor.SQL_QUERY_TOTAL_LINE); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getIssuerTypeCount] get the count of AuthorityIssuer error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + + @Override + public ResponseData> getIssuerTypeList(String domain, Integer first, Integer last) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Object[] datas = {first, last - first}; + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQueryLines(SqlExecutor.SQL_QUERY_SEVERAL_SPECIFIC_TYPE, datas); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[mysql->getIssuerTypeList] get the IssuerTypeList error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getEvidenceByHash(String domain, String hash) { + + if (StringUtils.isEmpty(hash)) { + logger.error("[mysql->getEvidenceByHash] the hash is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_EVIDENCE_BY_HASH, hash); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + EvidenceValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), EvidenceValue.class); + if (StringUtils.isNotBlank(tableData.getSigners())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getEvidenceByHash] getEvidenceByHash error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + + @Override + public ResponseData addEvidenceByHash(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey, String group_id) { + if (StringUtils.isEmpty(hashValue)) { + logger.error("[mysql->addEvidenceByHash] the hashValue is empty."); + return new ResponseData(FAILED_STATUS, KEY_INVALID); + } + try { + SqlDomain sqlDomain = new SqlDomain(domain); + if(extraKey.equals(StringUtils.EMPTY)){ + Object[] datas = {hashValue, signer, signature, log, updated, revoked, group_id}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_EVIDENCE_BY_HASH, datas); + } + Object[] datas = {hashValue, signer, signature, log, updated, revoked, extraKey, group_id}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_SAVE_EVIDENCE_EXTRAKEY, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->addEvidenceByHash] addEvidenceByHash error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addSignatureAndLogs(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey) { + try { + SqlDomain sqlDomain = new SqlDomain(domain); + Date now = sqlDomain.getNow(); + Object[] datas = {signer, signature, log, updated, revoked, extraKey, hashValue}; + return new SqlExecutor(sqlDomain).execute(SqlExecutor.SQL_UPDATE_EVIDENCE, datas); + } catch (WeIdBaseException e) { + logger.error("[mysql->addSignatureAndLogs] addSignatureAndLogs error.", e); + return new ResponseData(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getEvidenceByExtraKey(String domain, String extraKey) { + + if (StringUtils.isEmpty(extraKey)) { + logger.error("[mysql->getEvidenceByExtraKey] the hash is empty."); + return new ResponseData(null, KEY_INVALID); + } + try { + ResponseData result = new ResponseData(); + SqlDomain sqlDomain = new SqlDomain(domain); + ResponseData> response = new SqlExecutor(sqlDomain) + .executeQuery(SqlExecutor.SQL_QUERY_EVIDENCE_BY_EXTRAKEY, extraKey); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + EvidenceValue tableData = DataToolUtils.deserialize( + DataToolUtils.serialize(response.getResult()), EvidenceValue.class); + if (StringUtils.isNotBlank(tableData.getSigners())) { + result.setResult(tableData); + return new ResponseData<>(tableData, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST); + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + return result; + } catch (WeIdBaseException e) { + logger.error("[mysql->getEvidenceByExtraKey] getEvidenceByExtraKey error.", e); + return new ResponseData(null, e.getErrorCode()); + } + } + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/redis/RedisDomain.java b/src/main/java/com/webank/weid/suite/persistence/redis/RedisDomain.java new file mode 100644 index 00000000..67b7c506 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/redis/RedisDomain.java @@ -0,0 +1,56 @@ + + +package com.webank.weid.suite.persistence.redis; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.suite.persistence.BaseDomain; +import com.webank.weid.util.PropertyUtils; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Getter +public class RedisDomain extends BaseDomain { + + private static final Logger logger = LoggerFactory.getLogger(RedisDomain.class); + + public RedisDomain() { + resolveDomain(); + } + + public RedisDomain(String domainkey) { + this.key = domainkey; + resolveDomain(); + } + + private void resolveDomain() { + + if (StringUtils.isBlank(this.key)) { + this.key = DataDriverConstant.DOMAIN_DEFAULT_INFO; + } + this.value = PropertyUtils.getProperty(this.key); + + if (StringUtils.isBlank(this.value) + && DataDriverConstant.DOMAIN_DEFAULT_INFO.equals(this.key)) { + this.tableDomain = DEFAULT_TABLE; + + } else if (StringUtils.isNotBlank(this.value) + && this.value.split(VALUE_SPLIT_CHAR).length == 2) { + String[] domains = this.value.split(VALUE_SPLIT_CHAR); + this.baseDomain = domains[0]; + this.tableDomain = domains[1]; + } else if (this.key.equals(DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO)) { + this.tableDomain = DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO; + } else { + logger.error("[resolveDomain] the domain {{}:{}} is illegal.", + this.key, + this.value + ); + throw new WeIdBaseException(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL); + } + resolveDomainTimeout(); + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/redis/RedisExecutor.java b/src/main/java/com/webank/weid/suite/persistence/redis/RedisExecutor.java new file mode 100644 index 00000000..e045c503 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/redis/RedisExecutor.java @@ -0,0 +1,336 @@ + + +package com.webank.weid.suite.persistence.redis; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.suite.persistence.DefaultValue; +import com.webank.weid.util.DataToolUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.redisson.api.*; +import org.redisson.client.RedisException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * redis操作辅助类. + * + * @author karenli + */ +public class RedisExecutor { + + private static final Logger logger = LoggerFactory.getLogger(RedisExecutor.class); + + /** + * the split for value. + */ + private static final String VALUE_SPLIT_CHAR = ":"; + + private RedisDomain redisDomain; + + + + /** + * 根据domain创建Redis执行器. + * + * @param redisDomain the redisDomain + */ + public RedisExecutor(RedisDomain redisDomain) { + + if (redisDomain != null) { + this.redisDomain = redisDomain; + } else { + this.redisDomain = new RedisDomain(); + } + } + + /** + * 查询操作. + * + * @param tableDomain key的部分映射 + * @param datakey 查询所需要的数据 + * @param client redisson连接入口 + * @return 返回查询出来的单个数据 + */ + public ResponseData executeQuery(String tableDomain, String datakey, + RedissonClient client) { + + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + RBucket rbucket = client.getBucket(tableDomain + VALUE_SPLIT_CHAR + datakey); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(rbucket.get()); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", redisDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + /** + * 执行分页查询 + * + * @param tableDomain 表域 + * @param dataDomain 数据域 + * @param datas 数据 + * @param client 客户端 + * @return {@link ResponseData}<{@link List}<{@link String}>> + */ + public ResponseData> executeQueryLines(String tableDomain,String dataDomain, int[] datas, RedissonClient client) { + ResponseData> result = new ResponseData>(); + ArrayList list = new ArrayList<>(); + try { + if (client == null) { + return new ResponseData<>(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + + } + RScoredSortedSet scoredSortedSet = client.getScoredSortedSet(dataDomain); + Collection objects = scoredSortedSet.valueRange(datas[0], datas[1]); + for (Object object : objects) { + RBucket rbucket = client.getBucket(tableDomain + VALUE_SPLIT_CHAR + object); + list.add(rbucket.get()); + } + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(list); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", redisDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + /** + * 执行分页查询id + * + * @param dataDomain 数据域 + * @param datas 数据 + * @param client 客户端 + * @return {@link ResponseData}<{@link List}<{@link Integer}>> + */ + public ResponseData> executeQueryIdLines(String dataDomain, int[] datas, RedissonClient client) { + ResponseData> result = new ResponseData>(); + ArrayList list = new ArrayList<>(); + try { + if (client == null) { + return new ResponseData<>(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + + } + RScoredSortedSet scoredSortedSet = client.getScoredSortedSet(dataDomain); + Collection objects = scoredSortedSet.valueRange(datas[0], datas[1]); + for (Object object : objects) { + list.add((Integer) object); + } + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(list); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", redisDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + /** + * 执行查询总数 + * + * @param tableDomain 表域 + * @param client 客户端 + * @return {@link ResponseData}<{@link Integer}> + */ + public ResponseData executeQueryCount(String tableDomain, RedissonClient client) { + client.getScoredSortedSet(tableDomain); + ResponseData result = new ResponseData(); + try { + if (client == null) { + return new ResponseData<>(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + RScoredSortedSet scoredSortedSet = client.getScoredSortedSet(tableDomain); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(scoredSortedSet.size()); + } catch (Exception e) { + logger.error("Query data from {{}} with exception", redisDomain.getTableDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + return result; + } + + + /** + * 增加的执行方法. + * + * @param client redisson连接入口 + * @param dataKey Hash(id) + * @param datas 所需要的数据 + * @return 返回执行成功或失败 + */ + public ResponseData execute(RedissonClient client, String dataKey, Object... datas) { + + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + TransactionArgs transactionArgs = new TransactionArgs(); + DefaultValue value = new DefaultValue(); + if (datas.length == 6) { + transactionArgs.setRequestId((String) datas[0]); + transactionArgs.setMethod((String) datas[1]); + transactionArgs.setArgs((String) datas[2]); + transactionArgs.setTimeStamp((Long) datas[3]); + transactionArgs.setExtra((String)datas[4]); + transactionArgs.setBatch((String)datas[5]); + String valueString = DataToolUtils.serialize(transactionArgs); + RBucket rbucket = client.getBucket( + redisDomain.getTableDomain() + VALUE_SPLIT_CHAR + dataKey); + addIndexForDataKey(client,dataKey,redisDomain.getTableDomain()); + rbucket.set(valueString); + } else { + value.setData((String) datas[0]); + value.setId(dataKey); + value.setExpire(redisDomain.getExpire()); + if (datas.length == 3) { + value.setCreated((Date)datas[1]); + value.setUpdated((Date)datas[2]); + //datas.lenth==2时为UpDate + } else if (datas.length == 2) { + value.setUpdated((Date)datas[1]); + } + String valueString = DataToolUtils.serialize(value); + RBucket rbucket = client.getBucket( + redisDomain.getTableDomain() + VALUE_SPLIT_CHAR + dataKey); + //解决重复写问题 + if (datas.length == 3 && rbucket.get() != null) { + return + new ResponseData( + DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + addIndexForDataKey(client,dataKey,redisDomain.getTableDomain()); + rbucket.set(valueString); + } + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_SUCESS_STATUS); + + } catch (Exception e) { + logger.error("Update data into {{}} with exception", redisDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } + + /** + * 删除执行方法. + * + * @param dataKey Hash(id) + * @param client redisson连接入口 + * @return 返回执行成功或失败 + */ + public ResponseData executeDelete(String dataKey, RedissonClient client) { + + ResponseData result = new ResponseData(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + RBucket rbucket = client.getBucket( + redisDomain.getTableDomain() + VALUE_SPLIT_CHAR + dataKey); + if (rbucket.get() == null) { + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } else { + rbucket.delete(); + result.setErrorCode(ErrorCode.SUCCESS); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_SUCESS_STATUS); + } + } catch (Exception e) { + logger.error("Delete data into {{}} with exception", redisDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } + + /** + * 批量新增的语句. + * + * @param dataList 占位符所需要的数据 + * @param client redisson连接入口 + * @return 返回受影响的行数 + */ + public ResponseData batchAdd(List> dataList, RedissonClient client) { + + ResponseData result = new ResponseData(); + List value = new ArrayList<>(); + RBatch rbatch = client.createBatch(); + try { + if (client == null) { + return + new ResponseData(null, ErrorCode.PERSISTENCE_GET_CONNECTION_ERROR); + } + List values = dataList.get(dataList.size() - 1); + int size = values.size(); + for (List list : dataList) { + if (CollectionUtils.isEmpty(list) || list.size() != size) { + return + new ResponseData( + DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_BATCH_ADD_DATA_MISMATCH + ); + } + } + + for (int i = 0; i < size; i++) { + DefaultValue val = new DefaultValue(); + val.setId((String) dataList.get(0).get(i)); + val.setData((String)dataList.get(1).get(i)); + val.setExpire((Date)dataList.get(2).get(i)); + val.setCreated((Date)dataList.get(3).get(i)); + val.setUpdated((Date)dataList.get(4).get(i)); + value.add(val); + } + + for (DefaultValue val : value) { + rbatch.getBucket(redisDomain.getTableDomain() + VALUE_SPLIT_CHAR + val.getId()) + .setAsync(DataToolUtils.serialize(val)); + addIndexForDataKey(client,val.getId(),redisDomain.getTableDomain()); + } + BatchResult batchResult = rbatch.execute(); + + result.setResult(size); + } catch (RedisException e) { + logger.error("Batch add data to {{}} with exception", redisDomain.getBaseDomain(), e); + result.setErrorCode(ErrorCode.PERSISTENCE_EXECUTE_FAILED); + result.setResult(DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS); + } + return result; + } + + /** + * 为key添加索引方便分页查询 + * + * @param dataKey 数据关键 + * @param domain 域 + */ + public void addIndexForDataKey(RedissonClient client, String dataKey, String domain){ + RScoredSortedSet set = client.getScoredSortedSet(domain); + set.add(set.size(),dataKey); + } + + + +} diff --git a/src/main/java/com/webank/weid/suite/persistence/redis/RedissonConfig.java b/src/main/java/com/webank/weid/suite/persistence/redis/RedissonConfig.java new file mode 100644 index 00000000..d5d800b0 --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/redis/RedissonConfig.java @@ -0,0 +1,143 @@ + + +package com.webank.weid.suite.persistence.redis; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * redisson配置类. + * + * @author karenli 2020年7月3日 + */ +public class RedissonConfig { + + private static final Config config = new Config(); + //连接URL + private static final String redisUrl = PropertyUtils.getProperty( + DataDriverConstant.REDIS_URL); + + private static final List redisNodes = Arrays.asList(redisUrl.split(",")); + + private static final String password = PropertyUtils.getProperty( + DataDriverConstant.REDIS_PASSWORD); + + /** + * 单节点模式. + * + * @return 返回单节点模式的redissonclient. + */ + public RedissonClient redissonSingleClient() { + + String redisPrefix = DataDriverConstant.REDIS_SINGLE; + //数据库选择,默认为db0 + String databaseKey = redisPrefix + DataDriverConstant.REDIS_DATABASE; + String passwd = null; + if (StringUtils.isNoneBlank(password)) { + passwd = password; + } + int database = Integer.parseInt(PropertyUtils.getProperty( + databaseKey, DataDriverConstant.DATABASE_DEFAULT_VALUE)); + config.useSingleServer().setAddress("redis://" + redisUrl) + .setPassword(passwd) + .setDatabase(database); + RedissonClient client = Redisson.create(config); + return client; + } + + /** + * 集群模式. + * + * @return 返回集群模式的redissonclient. + */ + public RedissonClient redissonClusterClient() { + + //配置文件的前缀 + String redisPrefix = DataDriverConstant.REDIS_CLUSTER; + //连接空闲超时时间 + String idleConnectionTimeoutKey = + redisPrefix + DataDriverConstant.IDLE_CONNECTION_TIMEOUT; + int idleConnectionTimeout = Integer.parseInt(PropertyUtils.getProperty( + idleConnectionTimeoutKey, + DataDriverConstant.IDLE_CONNECTION_TIMEOUT_DEFAULT_VALUE)); + //连接超时时间 + String connectTimeoutKey = redisPrefix + DataDriverConstant.CONNECT_TIMEOUT; + int connectTimeout = Integer.parseInt(PropertyUtils.getProperty( + connectTimeoutKey, DataDriverConstant.CONNECT_TIMEOUT_DEFAULT_VALUE)); + //等待节点回复命令的时间 + String timeoutKey = redisPrefix + DataDriverConstant.TIMEOUT; + int timeout = Integer.parseInt(PropertyUtils.getProperty( + timeoutKey, DataDriverConstant.TIMEOUT_DEFAULT_VALUE)); + //从节点最小空闲连接数 + String slaveConnMinIdleSizeKey = + redisPrefix + DataDriverConstant.SLAVE_CONNECTION_MINIMUM_IDLE_SIZE; + int slaveConnMinIdleSize = Integer.parseInt(PropertyUtils.getProperty( + slaveConnMinIdleSizeKey, + DataDriverConstant.SLAVE_CONNECTION_MINIMUM_IDLE_SIZE_DEFAULT_VALUE)); + //从节点连接池大小 + String slaveConnPoolSizeKey = + redisPrefix + DataDriverConstant.SLAVE_CONNECTION_POOL_SIZE; + int slaveConnPoolSize = Integer.parseInt(PropertyUtils.getProperty( + slaveConnPoolSizeKey, + DataDriverConstant.SLAVE_CONNECTION_POOL_SIZE_DEFAULT_VALUE)); + //主节点最小空闲连接数 + String masterConnMinIdleSizeKey = + redisPrefix + DataDriverConstant.MASTER_CONNECTION_MINIMUM_IDLE_SIZE; + int masterConnMinIdleSize = Integer.parseInt(PropertyUtils.getProperty( + masterConnMinIdleSizeKey, + DataDriverConstant.MASTER_CONNECTION_MINIMUM_IDLE_SIZE_DEFAULT_VALUE)); + //主节点连接池大小 + String masterConnPoolSizeKey = + redisPrefix + DataDriverConstant.MASTER_CONNECTION_POOL_SIZE; + int masterConnPoolSize = Integer.parseInt(PropertyUtils.getProperty( + masterConnPoolSizeKey, + DataDriverConstant.MASTER_CONNECTION_POOL_SIZE_DEFAULT_VALUE)); + + //Url添加redis://前缀 + List clusterNodes = new ArrayList<>(); + for (int i = 0; i < redisNodes.size(); i++) { + clusterNodes.add("redis://" + redisNodes.get(i)); + } + //读取配置文件中的password,默认为null + String passwd = null; + if (StringUtils.isNoneBlank(password)) { + passwd = password; + } + + config.useClusterServers().addNodeAddress(clusterNodes.toArray( + new String[clusterNodes.size()])) + .setPassword(passwd) + .setIdleConnectionTimeout(idleConnectionTimeout) + .setConnectTimeout(connectTimeout) + .setTimeout(timeout) + .setSlaveConnectionMinimumIdleSize(slaveConnMinIdleSize) + .setSlaveConnectionPoolSize(slaveConnPoolSize) + .setMasterConnectionMinimumIdleSize(masterConnMinIdleSize) + .setMasterConnectionPoolSize(masterConnPoolSize); + + RedissonClient redisson = Redisson.create(config); + return redisson; + } + + /** + * 判断redis配置为单节点模式还是集群模式. + * + * @return 返回集群模式/单节点模式的redissonclient. + */ + public RedissonClient redismodelRecognition() { + + if (redisNodes.size() > 1) { + return redissonClusterClient(); + } else { + return redissonSingleClient(); + } + } +} diff --git a/src/main/java/com/webank/weid/suite/persistence/redis/driver/RedisDriver.java b/src/main/java/com/webank/weid/suite/persistence/redis/driver/RedisDriver.java new file mode 100644 index 00000000..25df16cd --- /dev/null +++ b/src/main/java/com/webank/weid/suite/persistence/redis/driver/RedisDriver.java @@ -0,0 +1,601 @@ + + +package com.webank.weid.suite.persistence.redis.driver; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.base.CptBaseInfo; +import com.webank.weid.blockchain.protocol.base.WeIdDocument; +import com.webank.weid.blockchain.protocol.base.WeIdDocumentMetadata; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.suite.persistence.*; +import com.webank.weid.suite.persistence.redis.RedisDomain; +import com.webank.weid.suite.persistence.redis.RedisExecutor; +import com.webank.weid.suite.persistence.redis.RedissonConfig; +import com.webank.weid.util.DataDriverUtils; +import com.webank.weid.util.DataToolUtils; +import org.apache.commons.lang3.StringUtils; +import org.redisson.api.RScoredSortedSet; +import org.redisson.api.RedissonClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +/** + * redis Driver. + * + * @author karenli + */ +public class RedisDriver implements Persistence { + + private static final Logger logger = LoggerFactory.getLogger(RedisDriver.class); + + private static final Integer FAILED_STATUS = DataDriverConstant.REDISSON_EXECUTE_FAILED_STATUS; + + private static final ErrorCode KEY_INVALID = ErrorCode.PRESISTENCE_DATA_KEY_INVALID; + + private static int CPT_DEFAULT_VERSION = 1; + + RedissonConfig redissonConfig = new RedissonConfig(); + + RedissonClient client = redissonConfig.redismodelRecognition(); + + @Override + public ResponseData add(String domain, String id, String data) { + + if (StringUtils.isEmpty(id)) { + logger.error("[redis->add] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + RedisDomain redisDomain = new RedisDomain(domain); + Date date = new Date(); + Object[] datas = {data, date, date}; + return new RedisExecutor(redisDomain).execute(client, dataKey, datas); + } catch (WeIdBaseException e) { + logger.error("[redis->add] add the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData batchAdd(String domain, Map keyValueList) { + + try { + List idHashList = new ArrayList<>(); + List dataList = new ArrayList<>(); + for (String id : keyValueList.keySet()) { + String data = keyValueList.get(id); + if (StringUtils.isEmpty(id)) { + logger.error("[redis->batchAdd] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + idHashList.add(DataToolUtils.hash(id)); + dataList.add(data); + } + RedisDomain redisDomain = new RedisDomain(domain); + List> dataLists = new ArrayList<>(); + dataLists.add(idHashList); + dataLists.add(Arrays.asList(dataList.toArray())); + //处理失效时间 + dataLists.add(fixedListWithDefault(idHashList.size(), redisDomain.getExpire())); + //处理创建时间和更新时间 + List nowList = fixedListWithDefault(idHashList.size(), redisDomain.getNow()); + dataLists.add(nowList); + dataLists.add(nowList); + return new RedisExecutor(redisDomain).batchAdd(dataLists, client); + } catch (WeIdBaseException e) { + logger.error("[redis->batchAdd] batchAdd the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + private List fixedListWithDefault(int size, Object obj) { + + Object[] dates = new Object[size]; + Arrays.fill(dates, obj); + List list = new ArrayList<>(); + list.addAll(Arrays.asList(dates)); + return list; + } + + @Override + public ResponseData get(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[redis->get] the id of the data is empty."); + return new ResponseData<>(StringUtils.EMPTY, KEY_INVALID); + } + //dataKey:id的hash值 + String dataKey = DataToolUtils.hash(id); + try { + ResponseData result = new ResponseData<>(); + //设置result初始值为空字符串 + result.setResult(StringUtils.EMPTY); + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQuery(redisDomain.getTableDomain(), dataKey, client); + + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + DefaultValue data = DataToolUtils.deserialize( + response.getResult(), DefaultValue.class); + //超过超时时间,log输出data超时 + if (data != null && data.getExpire() != null + && data.getExpire().before(new Date())) { + logger.error("[redis->get] the data is expire."); + //输出empty以及超过超时时间错误代码 + return new ResponseData<>(StringUtils.EMPTY, + ErrorCode.PERSISTENCE_DATA_EXPIRE); + } + if (data != null && StringUtils.isNotBlank(data.getData())) { + result.setResult( + new String( + data.getData().getBytes( + DataDriverConstant.STANDARDCHARSETS_ISO), + DataDriverConstant.STANDARDCHARSETS_UTF_8 + ) + ); + } + } + result.setErrorCode(ErrorCode.getTypeByErrorCode(response.getErrorCode())); + System.out.println("result=" + result.getResult()); + System.out.println(result.getResult() == null); + return result; + } catch (WeIdBaseException e) { + logger.error("[redis->get] get the data error.", e); + return new ResponseData<>(StringUtils.EMPTY, e.getErrorCode()); + } + } + + @Override + public ResponseData delete(String domain, String id) { + + if (StringUtils.isEmpty(id)) { + logger.error("[redis->delete] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + try { + RedisDomain redisDomain = new RedisDomain(domain); + return new RedisExecutor(redisDomain).executeDelete(dataKey, client); + } catch (WeIdBaseException e) { + logger.error("[redis->delete] delete the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData update(String domain, String id, String data) { + + if (StringUtils.isEmpty(id) || StringUtils.isBlank(this.get(domain, id).getResult())) { + logger.error("[redis->update] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(id); + Date date = new Date(); + try { + RedisDomain redisDomain = new RedisDomain(domain); + Object[] datas = {data, date}; + return new RedisExecutor(redisDomain).execute(client, dataKey, datas); + } catch (WeIdBaseException e) { + logger.error("[redis->update] update the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData addOrUpdate(String domain, String id, String data) { + + ResponseData getRes = this.get(domain, id); + //如果查询数据存在,或者失效 则进行更新 否则进行新增 + if ((StringUtils.isNotBlank(getRes.getResult()) + && getRes.getErrorCode() == ErrorCode.SUCCESS.getCode()) + || + getRes.getErrorCode() == ErrorCode.PERSISTENCE_DATA_EXPIRE.getCode()) { + return this.update(domain, id, data); + } + return this.add(domain, id, data); + } + + @Override + public ResponseData addTransaction(TransactionArgs transactionArgs) { + + if (StringUtils.isEmpty(transactionArgs.getRequestId())) { + logger.error("[redis->add] the id of the data is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + try { + RedisDomain redisDomain = new RedisDomain( + DataDriverConstant.DOMAIN_OFFLINE_TRANSACTION_INFO); + String datakey = transactionArgs.getRequestId(); + Object[] datas = { + transactionArgs.getRequestId(), + transactionArgs.getMethod(), + transactionArgs.getArgs(), + transactionArgs.getTimeStamp(), + transactionArgs.getExtra(), + transactionArgs.getBatch() + }; + return new RedisExecutor(redisDomain).execute(client, datakey, datas); + } catch (WeIdBaseException e) { + logger.error("[redis->add] add the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + /* + 以下方法暂不需要,本地部署不需要使用redis方式,默认使用Mysql + */ + + @Override + public ResponseData addWeId(String domain, String weId, String documentSchema) { + if (StringUtils.isEmpty(weId)) { + logger.error("[redis->addWeId] the weId is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + try { + RedisDomain redisDomain = new RedisDomain(domain); + Date now = redisDomain.getNow(); + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setUpdated(now); + value.setCreated(now); + value.setDeactivated(0); + value.setDocument_schema(documentSchema); + String data = DataToolUtils.serialize(value); + + return add(domain,weId,data); + } catch (WeIdBaseException e) { + logger.error("[redis->addWeId] add the data error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData updateWeId(String domain, String weId, String documentSchema) { + if (StringUtils.isEmpty(weId)) { + logger.error("[redis->updateWeId] the weId is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(weId); + Date date = new Date(); + try { + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQuery(redisDomain.getTableDomain(), dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj( + response.getResult(), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[redis->updateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + int version = tableData.getVersion(); + version++; + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setUpdated(date); + value.setCreated(tableData.getCreated()); + value.setDeactivated(tableData.getDeactivated()); + value.setDocument_schema(documentSchema); + value.setVersion(version); + String data = com.webank.weid.blockchain.util.DataToolUtils.serialize(value); + return update(domain,weId,data); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[redis->updateWeId] update the weid error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdDocument(String domain, String weId) { + if (StringUtils.isEmpty(weId)) { + logger.error("[redis->getWeIdDocument] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + try { + String dataKey = DataToolUtils.hash(weId); + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQuery(redisDomain.getTableDomain(), dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj(response.getResult(), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + return new ResponseData<>(WeIdDocument.fromJson(tableData.getDocument_schema()), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } catch (WeIdBaseException e) { + logger.error("[redis->getWeIdDocument] get the weIdDocument error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getMeta(String domain, String weId) { + if (StringUtils.isEmpty(weId)) { + logger.error("[redis->getMeta] the weId is empty."); + return new ResponseData<>(null, KEY_INVALID); + } + try { + String dataKey = DataToolUtils.hash(weId); + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQuery(redisDomain.getTableDomain(), dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj(response.getResult(), WeIdDocumentValue.class); + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + WeIdDocumentMetadata weIdDocumentMetadata = new WeIdDocumentMetadata(); + weIdDocumentMetadata.setCreated(tableData.getCreated().getTime()); + weIdDocumentMetadata.setUpdated(tableData.getUpdated().getTime()); + weIdDocumentMetadata.setVersionId(tableData.getVersion()); + weIdDocumentMetadata.setDeactivated(tableData.getDeactivated() == 1); + return new ResponseData<>(weIdDocumentMetadata, ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.WEID_DOES_NOT_EXIST); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[redis->getMeta] getMeta error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData deactivateWeId(String domain, String weId, Boolean state) { + + if (StringUtils.isEmpty(weId)) { + logger.error("[redis->deactivateWeId] the weId is empty."); + return new ResponseData<>(FAILED_STATUS, KEY_INVALID); + } + String dataKey = DataToolUtils.hash(weId); + Date date = new Date(); + try { + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQuery(redisDomain.getTableDomain(), dataKey, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + WeIdDocumentValue tableData = DataDriverUtils.decodeValueForNeedObj( + response.getResult(), WeIdDocumentValue.class); + if(tableData.getDeactivated() == 1){ + logger.error("[ipfs->deactivateWeId] the weid is deactivated."); + return new ResponseData<>(FAILED_STATUS, + ErrorCode.WEID_HAS_BEEN_DEACTIVATED); + } + if (StringUtils.isNotBlank(tableData.getDocument_schema())) { + WeIdDocumentValue value = new WeIdDocumentValue(); + value.setWeid(weId); + value.setDocument_schema(tableData.getDocument_schema()); + value.setCreated(tableData.getCreated()); + value.setUpdated(date); + value.setVersion(tableData.getVersion()); + value.setDeactivated(state?1:0); + String data = DataToolUtils.serialize(value); + return update(domain,data,dataKey); + } + } + return new ResponseData<>(FAILED_STATUS, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[redis->deactivateWeId] deactivate the weId error.", e); + return new ResponseData<>(FAILED_STATUS, e.getErrorCode()); + } + } + + @Override + public ResponseData> getWeIdList(String domain, Integer first, Integer last) { + try { + RedisDomain redisDomain = new RedisDomain(domain); + int[] datas = {first, last - first + 1}; + ResponseData> response = new RedisExecutor(redisDomain).executeQueryLines( + redisDomain.getTableDomain(),redisDomain.getTableDomain(),datas, client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(DataDriverUtils.decodeValueToNeedListJson(response.getResult()), ErrorCode.SUCCESS); + } + return new ResponseData<>(null, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[redis->getWeIdList] get the data error.", e); + return new ResponseData<>(null, e.getErrorCode()); + } + } + + @Override + public ResponseData getWeIdCount(String domain) { + try { + RedisDomain redisDomain = new RedisDomain(domain); + ResponseData response = new RedisExecutor(redisDomain) + .executeQueryCount(redisDomain.getTableDomain(), client); + if (response.getErrorCode() == ErrorCode.SUCCESS.getCode() + && response.getResult() != null) { + return new ResponseData<>(response.getResult(), ErrorCode.SUCCESS); + } + return new ResponseData<>(0, ErrorCode.getTypeByErrorCode(response.getErrorCode())); + } catch (WeIdBaseException e) { + logger.error("[redis->getWeIdCount] get the data error.", e); + return new ResponseData<>(0, e.getErrorCode()); + } + } + //** + //目前只实现了WeId相关接口 + @Override + public ResponseData getCpt(String domain, int cptId) { + return null; + } + + @Override + public ResponseData addCpt(String domain, int cptId, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData getPolicy(String domain, int policyId) { + return null; + } + + @Override + public ResponseData addPolicy(String domain, int policyId, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData getPresentation(String domain, int presentationId) { + return null; + } + + @Override + public ResponseData addPresentation(String domain, int presentationId, String creator, String policies) { + return null; + } + + @Override + public ResponseData updateCpt(String domain, int cptId, int cptVersion, String publisher, String description, String cptSchema, String cptSignature) { + return null; + } + + @Override + public ResponseData updateCredentialTemplate(String domain, int cptId, String credentialPublicKey, String credentialProof) { + return null; + } + + @Override + public ResponseData updateCptClaimPolicies(String domain, int cptId, String policies) { + return null; + } + + @Override + public ResponseData> getCptIdList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData getCptCount(String domain) { + return null; + } + + @Override + public ResponseData> getPolicyIdList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData getPolicyCount(String domain) { + return null; + } + + @Override + public ResponseData addAuthorityIssuer(String domain, String weId, String name, String desc, String accValue, String extraStr, String extraInt) { + return null; + } + + @Override + public ResponseData removeAuthorityIssuer(String domain, String weId) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerByWeId(String domain, String weId) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerByName(String domain, String name) { + return null; + } + + @Override + public ResponseData updateAuthorityIssuer(String domain, String weId, Integer recognize) { + return null; + } + + @Override + public ResponseData getAuthorityIssuerCount(String domain) { + return null; + } + + @Override + public ResponseData getRecognizedIssuerCount(String domain) { + return null; + } + + @Override + public ResponseData addRole(String domain, String weId, Integer roleValue) { + return null; + } + + @Override + public ResponseData getRole(String domain, String weId) { + return null; + } + + @Override + public ResponseData updateRole(String domain, String weId, Integer roleValue) { + return null; + } + + @Override + public ResponseData addSpecificType(String domain, String typeName, String owner) { + return null; + } + + @Override + public ResponseData getSpecificType(String domain, String typeName) { + return null; + } + + @Override + public ResponseData removeSpecificType(String domain, String typeName) { + return null; + } + + @Override + public ResponseData updateSpecificTypeFellow(String domain, String typeName, String fellow) { + return null; + } + + @Override + public ResponseData getIssuerTypeCount(String domain) { + return null; + } + + @Override + public ResponseData> getIssuerTypeList(String domain, Integer first, Integer last) { + return null; + } + + @Override + public ResponseData addEvidenceByHash(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey, String group_id) { + return null; + } + + @Override + public ResponseData getEvidenceByHash(String domain, String hash) { + return null; + } + + @Override + public ResponseData addSignatureAndLogs(String domain, String hashValue, String signer, String signature, String log, String updated, String revoked, String extraKey) { + return null; + } + + @Override + public ResponseData getEvidenceByExtraKey(String domain, String extraKey) { + return null; + } + + + +} diff --git a/src/main/java/com/webank/weid/util/BatchTransactionUtils.java b/src/main/java/com/webank/weid/util/BatchTransactionUtils.java new file mode 100644 index 00000000..84a60ec1 --- /dev/null +++ b/src/main/java/com/webank/weid/util/BatchTransactionUtils.java @@ -0,0 +1,292 @@ +package com.webank.weid.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceType; + +/** + * 批量交易处理类. + * + * @author tonychen 2020年4月1日 + */ +public class BatchTransactionUtils { + + private static final Logger logger = LoggerFactory.getLogger(BatchTransactionUtils.class); + + /** + * 阈值,当写入的交易达到这个条数时,换新文件. + */ + private static final Integer THRESHOLD = 10000; + private static OutputStreamWriter ow = null; + private static String secretKey; + private static String currentFilePath; + + /** + * 本机IP地址. + */ + private static String ipAddr; + private static Integer count; + private static String currentDir = System.getProperty("user.dir"); + private static boolean isSaveToDb = true; + + /** + * persistence. + */ + private static Persistence dataDriver; + private static PersistenceType persistenceType; + private static Integer index = 0; + private static String currentDay; + + static { + Date date = new Date(); + currentDay = new SimpleDateFormat("yyyyMMdd").format(date); + } + + /** + * 获取本机IP. + * + * @return 本机IP地址 + */ + private static String getIp() { + + if (!StringUtils.isBlank(ipAddr)) { + return ipAddr; + } + InetAddress address = null; + try { + address = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + logger.error("[getIp] get local ip failed. Error message:{}", e); + return null; + } + ipAddr = address.getHostAddress(); + return ipAddr; + } + + private static Persistence getDataDriver() { + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + if (dataDriver == null) { + dataDriver = PersistenceFactory.build(persistenceType); + } + return dataDriver; + } + + /** + * 获取用来加密私钥的对称秘钥. + * + * @return 对称秘钥 + */ + private static String getKey() { + + if (!StringUtils.isBlank(secretKey)) { + return secretKey; + } else { + ResponseData dbResp = getDataDriver().get(DataDriverConstant.DOMAIN_ENCRYPTKEY, + PropertyUtils.getProperty("blockchain.orgid")); + Integer errorCode = dbResp.getErrorCode(); + if (errorCode != ErrorCode.SUCCESS.getCode()) { + logger + .error("[writeTransaction] save encrypt private key to db failed.errorcode:{}", + errorCode); + return null; + } + secretKey = dbResp.getResult(); + return secretKey; + } + } + + /** + * 记录交易记录,后续采用离线批处理的方式写入区块链. + * + * @param requestId 对应本次交易的id + * @param method 交易方法 + * @param args 交易参数 + * @param extra 额外信息 + * @return 如果成功,返回true,否则flase + */ + public static boolean writeTransaction( + String requestId, + String method, + String[] args, + String extra) { + + String parameters = processArgs(args); + if (parameters == null) { + logger.error("[writeTransaction] parameters is illegal. requestId:{},method:{}", + requestId, + method); + return false; + } + long timeStamp = System.currentTimeMillis(); + if (isSaveToDb) { + TransactionArgs transactionArgs = new TransactionArgs(); + transactionArgs.setArgs(parameters); + transactionArgs.setBatch(getCurrentDay()); + transactionArgs.setExtra(extra); + transactionArgs.setMethod(method); + transactionArgs.setRequestId(requestId); + transactionArgs.setTimeStamp(timeStamp); + return saveToDb(transactionArgs); + } + + String content = new StringBuffer() + .append(requestId) + .append(WeIdConstant.PIPELINE) + .append(method) + .append(WeIdConstant.PIPELINE) + .append(parameters) + .append(WeIdConstant.PIPELINE) + .append(extra) + .append(WeIdConstant.PIPELINE) + .append(timeStamp).toString(); + + String filePath = getFilePath(); + return saveToLogFile(content, filePath); + } + + private static String getCurrentDay() { + + Date date = new Date(); + String currentDate = new SimpleDateFormat("yyyyMMdd").format(date); + return currentDate; + } + + /** + * 交易保存至数据库. + * + * @return 状态 + */ + private static boolean saveToDb(TransactionArgs transaction) { + + ResponseData dbResp = getDataDriver().addTransaction(transaction); + if (dbResp.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return false; + } + return true; + } + + private static String getFilePath() { + + String currentDate = getCurrentDay(); + if (!StringUtils.equals(currentDay, currentDate)) { + index = 0; + count = 0; + } + String filePath = + currentDir + File.separator + currentDate + File.separator + getIp() + "_binlog_" + + index; + if (StringUtils.equals(currentFilePath, filePath)) { + count++; + //如果记录条数超过阈值,要换文件 + if (count >= THRESHOLD) { + index++; + } + } else { + currentFilePath = filePath; + count = 1; + } + return filePath; + } + + private static String processArgs(String[] args) { + + if (args == null || args.length == 0) { + + return null; + } + int length = args.length; + StringBuffer content = new StringBuffer(); + for (int i = 0; i < length - 2; i++) { + + content.append(args[i]).append(","); + } + String privateKey = args[length - 2]; + + String weId = WeIdUtils.getWeIdFromPrivateKey(privateKey); + + //将私钥进行对称加密后存到数据库里 + //String encryptKey = CryptServiceFactory.getCryptService(CryptType.AES) + // .encrypt(privateKey, getKey()); + //ResponseData dbResp = getDataDriver() + // .addOrUpdate(DataDriverConstant.DOMAIN_ENCRYPTKEY, weId, encryptKey); + //Integer errorCode = dbResp.getErrorCode(); + //if (errorCode != ErrorCode.SUCCESS.getCode()) { + // logger.error("[writeTransaction] save encrypt private key to db failed.errorcode:{}", + // errorCode); + // return null; + //} + + content.append(weId).append(","); + content.append(args[length - 1]); + return content.toString(); + } + + /** + * 将交易信息写入binlog. + * + * @param content 要写入的内容 + * @param fileName 文件名 + */ + private static boolean saveToLogFile( + String content, + String fileName) { + + File f = new File(fileName); + File parent = f.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + if (!f.exists()) { + try { + f.createNewFile(); + } catch (IOException e) { + logger.error("[writeToLogFile] create file failed. filePath:{}, error:{}", fileName, + e); + return false; + } + } + try { + ow = new OutputStreamWriter(new FileOutputStream(fileName, true), + ParamKeyConstant.UTF_8); + ow.write(content); + ow.close(); + return true; + } catch (IOException e) { + logger.error("writer file exception.", e); + } finally { + if (null != ow) { + try { + ow.close(); + } catch (IOException e) { + logger.error("io close exception.", e); + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/com/webank/weid/util/CredentialPojoUtils.java b/src/main/java/com/webank/weid/util/CredentialPojoUtils.java new file mode 100644 index 00000000..870990e0 --- /dev/null +++ b/src/main/java/com/webank/weid/util/CredentialPojoUtils.java @@ -0,0 +1,1030 @@ + + +package com.webank.weid.util; + +import com.webank.weid.constant.*; +import com.webank.weid.constant.CredentialConstant.CredentialProofType; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import org.apache.commons.collections4.CollectionUtils; +import com.webank.weid.blockchain.constant.ErrorCode; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static com.webank.weid.service.impl.CredentialPojoServiceImpl.generateSalt; + +/** + * The Class CredentialUtils. + * + * @author chaoxinhu 2019.1 + */ +public final class CredentialPojoUtils { + + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(CredentialPojoUtils.class); + + private static Integer NOT_DISCLOSED = + CredentialFieldDisclosureValue.NOT_DISCLOSED.getStatus(); + + /** + * Concat all fields of Credential info, without Signature, in Json format. This should be + * invoked when calculating Credential Signature. Return null if credential format is illegal. + * Note that: 1. Keys should be dict-ordered; 2. Claim should use standard getClaimHash() to + * support selective disclosure; 3. Use compact output to avoid Json format confusion. + * + * @param credential target Credential object + * @param salt Salt Map + * @param disclosures Disclosure Map + * @return Hash value in String. + */ + public static String getCredentialThumbprintWithoutSig( + CredentialPojo credential, + Map salt, + Map disclosures) { + try { + Map credMap = DataToolUtils.objToMap(credential); + // Preserve the same behavior as in CredentialUtils - will merge later + credMap.remove(ParamKeyConstant.PROOF); + credMap.put(ParamKeyConstant.CLAIM, getClaimHash(credential, salt, disclosures)); + return DataToolUtils.mapToCompactJson(credMap); + } catch (Exception e) { + logger.error("get Credential Thumbprint WithoutSig error.", e); + return StringUtils.EMPTY; + } + } + + /** + * Concat all fields of lite Credential info, without Signature, in Json format. This should be + * invoked when calculating Credential Signature. Return null if credential format is illegal. + * Note that: 1. Keys should be dict-ordered; 2. Claim should use standard getLiteClaimHash(); + * 3. Use compact output to avoid Json format confusion. + * + * @param credential target Credential object + * @return Hash value in String. + */ + public static String getLiteCredentialThumbprintWithoutSig( + CredentialPojo credential) { + try { + Map credMap = DataToolUtils.objToMap(credential); + //credMap.remove(ParamKeyConstant.ISSUANCE_DATE); + credMap.remove(ParamKeyConstant.CONTEXT); + credMap.put(ParamKeyConstant.PROOF_TYPE, "lite1"); + // Preserve the same behavior as in CredentialUtils - will merge later + credMap.remove(ParamKeyConstant.PROOF); + credMap.put(ParamKeyConstant.CLAIM, getLiteClaimHash(credential)); + return DataToolUtils.mapToCompactJson(credMap); + } catch (Exception e) { + logger.error("get Credential Thumbprint WithoutSig error.", e); + return StringUtils.EMPTY; + } + } + + /** + * Check if the two credentials are equal. Will traverse each field. + * + * @param credOld first credential + * @param credNew second credential + * @return true if yes, false otherwise + */ + public static boolean isEqual(CredentialPojo credOld, CredentialPojo credNew) { + if (credOld == null && credNew == null) { + return true; + } + if (credOld == null || credNew == null) { + return false; + } + return isProofContentEqual(credOld.getProof(), credNew.getProof()) + && credOld.getCptId().equals(credNew.getCptId()) + && credOld.getExpirationDate().equals(credNew.getExpirationDate()) + && credOld.getType().equals(credNew.getType()) + && credOld.getHash().equalsIgnoreCase(credNew.getHash()) + && credOld.getContext().equalsIgnoreCase(credNew.getContext()) + && credOld.getId().equalsIgnoreCase(credNew.getId()) + && credOld.getIssuanceDate().equals(credNew.getIssuanceDate()) + && credOld.getIssuer().equalsIgnoreCase(credNew.getIssuer()); + } + + private static boolean isProofContentEqual(Object a, Object b) { + if (a instanceof Map && b instanceof Map) { + Set keySet = ((Map) a).keySet(); + Set keySetb = ((Map) b).keySet(); + for (String key : keySet) { + if (!keySetb.contains(key)) { + return false; + } + } + for (String key : keySetb) { + if (!keySet.contains(key)) { + return false; + } + } + boolean equals = true; + for (String key : keySet) { + equals = isProofContentEqual(((Map) a).get(key), ((Map) b).get(key)); + if (!equals) { + return false; + } + } + } else if (a instanceof String && b instanceof String) { + return ((String) a).equalsIgnoreCase((String) b); + } else if (a instanceof Number && b instanceof Number) { + return ((Number) a).intValue() == ((Number) b).intValue(); + } + return true; + } + + /** + * Concat all fields of Credential info, with signature. This should be invoked when calculating + * Credential Evidence. Return null if credential format is illegal. + * + * @param credential target Credential object + * @param salt Salt Map + * @param disclosures Disclosure Map + * @return Hash value in String. + */ + private static String getCredentialPojoRawDataWithProofWithoutSalt( + CredentialPojo credential, + Map salt, + Map disclosures + ) { + try { + Map credMap = DataToolUtils.objToMap(credential); + // Replace the Claim value object with claim hash value to preserve immutability + credMap.put(ParamKeyConstant.CLAIM, getClaimHash(credential, salt, disclosures)); + // Remove the whole Salt field to preserve immutability + Map proof = (Map) credMap.get(ParamKeyConstant.PROOF); + proof.remove(ParamKeyConstant.PROOF_SALT); + proof.put(ParamKeyConstant.PROOF_SALT, null); + credMap.remove(ParamKeyConstant.PROOF); + credMap.put(ParamKeyConstant.PROOF, proof); + return DataToolUtils.mapToCompactJson(credMap); + } catch (Exception e) { + logger.error("get Credential Thumbprint error.", e); + return StringUtils.EMPTY; + } + } + + /** + * Create a full CredentialPojo Hash for a Credential based on all its fields, which is + * resistant to selective disclosure. + * + * @param credentialPojo target Credential object + * @param disclosures Disclosure Map + * @return Hash value in String. + */ + public static String getCredentialPojoHash(CredentialPojo credentialPojo, + Map disclosures) { + String rawData = getCredentialPojoRawDataWithProofWithoutSalt( + credentialPojo, + credentialPojo.getSalt(), + disclosures); + if (StringUtils.isEmpty(rawData)) { + return StringUtils.EMPTY; + } + // System.out.println(rawData); + return DataToolUtils.hash(rawData); + } + + /** + * Create a full lite CredentialPojo Hash for a Credential based on all its fields. + * + * @param credentialPojo target Credential object + * @return Hash value in String. + */ + public static String getLiteCredentialPojoHash(CredentialPojo credentialPojo) { + + try { + Map credMap = DataToolUtils.objToMap(credentialPojo); + credMap.remove(ParamKeyConstant.CONTEXT); + credMap.put(ParamKeyConstant.PROOF_TYPE, "lite1"); + credMap.remove(ParamKeyConstant.PROOF); + String signature = credentialPojo.getSignature(); + credMap.put(ParamKeyConstant.PROOF, signature); + credMap.put(ParamKeyConstant.CLAIM, getLiteClaimHash(credentialPojo)); + String rawData = DataToolUtils.mapToCompactJson(credMap); + //System.out.println("LiteCredential's Pre-Hash for evidence: " + rawData); + return DataToolUtils.hash(rawData); + } catch (Exception e) { + logger.error("get Credential Thumbprint error.", e); + return StringUtils.EMPTY; + } + } + + /** + * Concat the credential list (embedded) into a selective disclosure resistant String. + * + * @param credentialList the credential list + * @return the String + */ + public static String getEmbeddedCredentialThumbprintWithoutSig( + List credentialList) { + String result = StringUtils.EMPTY; + // 1. sort against id + Map credMap = new HashMap<>(); + for (CredentialPojo credential : credentialList) { + credMap.put(credential.getId(), credential); + } + Map treeMap = new TreeMap<>(credMap); + List credList = new ArrayList<>(); + for (String id : treeMap.keySet()) { + credList.add(treeMap.get(id)); + } + // 2. do recursive compute + for (CredentialPojo credential : credList) { + if (!isEmbeddedCredential(credential)) { + result += getCredentialPojoHash(credential, null); + } else { + List objList = (ArrayList) credential.getClaim() + .get("credentialList"); + List newList = new ArrayList<>(); + try { + for (Object obj : objList) { + if (obj instanceof CredentialPojo) { + newList.add((CredentialPojo) obj); + } else { + newList.add(DataToolUtils + .mapToObj((HashMap) obj, CredentialPojo.class)); + } + } + } catch (Exception e) { + logger.error("Failed to convert credentialPojo: " + e.getMessage()); + return null; + } + result += getEmbeddedCredentialThumbprintWithoutSig(newList); + } + } + return result; + } + + /** + * Check whether a Credential is an embedded credential. Embedded Credential does not support + * Selective disclosure and its proof is empty. + * + * @param credential the credentialPojo + * @return true if yes, false otherwise + */ + public static boolean isEmbeddedCredential(CredentialPojo credential) { + int cptId = credential.getCptId(); + return cptId == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + || cptId == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT + || cptId == CredentialConstant.EMBEDDED_TIMESTAMP_CPT + || cptId == CredentialConstant.TIMESTAMP_ENVELOP_CPT; + } + + /** + * Convert a credential to fully undisclosed. + * + * @param credential the credential + * @return true if yes, false otherwise + */ + public static boolean convertToFullyUndisclose(CredentialPojo credential) { + return false; + } + + /** + * Check whether a CPT ID is system CPT ID. + * + * @param id CPT ID + * @return true if yes, false otherwise + */ + public static boolean isSystemCptId(Integer id) { + int cptId = id.intValue(); + return cptId == CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT + || cptId == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT + || cptId == CredentialConstant.EMBEDDED_TIMESTAMP_CPT + || cptId == CredentialConstant.TIMESTAMP_ENVELOP_CPT + || cptId == CredentialConstant.AUTHORIZATION_CPT + || cptId == CredentialConstant.CHALLENGE_CPT + || cptId == CredentialConstant.CHALLENGE_VERIFICATION_CPT + || cptId == CredentialConstant.CLAIM_POLICY_CPT + || cptId == CredentialConstant.SERVICE_ENDPOINT_CPT; + } + + /** + * Convert a fully-disclosed credentialPojo to fully non-disclosed. Multi-sign credentialPojo, + * and partially disclosed credentialPojo are not allowed in this case. + * + * @param credential the credential + * @return the fully non-disclosed credential + */ + public static ClaimPolicy generateNonDisclosedPolicy(CredentialPojo credential) { + if (credential.getCptId().intValue() + == CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT) { + logger.error("Cannot convert a multi-sign credential to non-disclosed - meaningless."); + return null; + } + if (CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt())) { + logger.error("Cannot do re-selectively disclose to a credential."); + return null; + } + HashMap claimMap = (HashMap) credential.getClaim(); + Map policyMap = DataToolUtils.clone(claimMap); + generateSalt(policyMap, 0); + String policyStr = DataToolUtils.serialize(policyMap); + ClaimPolicy policy = new ClaimPolicy(); + policy.setFieldsToBeDisclosed(policyStr); + return policy; + } + + /** + * Check if the given CredentialPojo is selectively disclosed, or not. + * + * @param saltMap the saltMap + * @return true if yes, false otherwise + */ + public static boolean isSelectivelyDisclosed(Map saltMap) { + if (saltMap == null) { + return false; + } + for (Map.Entry entry : saltMap.entrySet()) { + Object v = entry.getValue(); + if (v instanceof Map) { + if (isSelectivelyDisclosed((HashMap) v)) { + return true; + } + } else if (v instanceof List) { + if (isSelectivelyDisclosed((ArrayList) v)) { + return true; + } + } + if (v == null) { + throw new WeIdBaseException(ErrorCode.CREDENTIAL_SALT_ILLEGAL); + } + if ("0".equals(v.toString())) { + return true; + } + } + return false; + } + + /** + * Check if the given CredentialPojo is selectively disclosed, or not. + * + * @param saltList the saltList + * @return true if yes, false otherwise + */ + public static boolean isSelectivelyDisclosed(List saltList) { + if (saltList == null) { + return false; + } + for (Object saltObj : saltList) { + if (saltObj instanceof Map) { + if (isSelectivelyDisclosed((HashMap) saltObj)) { + return true; + } + } else if (saltObj instanceof List) { + if (isSelectivelyDisclosed((ArrayList) saltObj)) { + return true; + } + } + if (saltObj == null) { + throw new WeIdBaseException(ErrorCode.CREDENTIAL_SALT_ILLEGAL); + } + if ("0".equals(saltObj.toString())) { + return true; + } + } + return false; + } + + /** + * Check whether a credential list contains any selectively disclosed credential. + * + * @param credentialList the credential list + * @return true if yes, false otherwise + */ + public static boolean isSelectivelyDisclosedCredentialList( + List credentialList) { + boolean notFound = true; + for (CredentialPojo credentialPojo : credentialList) { + if (isEmbeddedCredential(credentialPojo)) { + // recursive check for inner credential + try { + notFound = (notFound & !(isSelectivelyDisclosedCredentialList( + (ArrayList) credentialPojo.getClaim() + .get("credentialList")))); + } catch (Exception e) { + return false; + } + } else { + notFound = (notFound & !isSelectivelyDisclosed(credentialPojo.getSalt())); + } + if (!notFound) { + return true; + } + } + return false; + } + + /** + * Get the lite credential claim hash. + * + * @param credential Credential + * @return the claimMap value + */ + public static Map getLiteClaimHash( + CredentialPojo credential) { + + Map claim = credential.getClaim(); + return DataToolUtils.clone((HashMap) claim); + } + + /** + * Get the claim hash. This is irrelevant to selective disclosure. + * + * @param credential Credential + * @param salt Salt Map + * @param disclosures Disclosure Map + * @return the claimMap value + */ + public static Map getClaimHash( + CredentialPojo credential, + Map salt, + Map disclosures + ) { + + Map claim = credential.getClaim(); + Map newClaim = DataToolUtils.clone((HashMap) claim); + addSaltAndGetHash(newClaim, salt, disclosures); + return newClaim; + } + + private static void addSaltAndGetHash( + Map claim, + Map salt, + Map disclosures + ) { + for (Map.Entry entry : salt.entrySet()) { + String key = entry.getKey(); + Object disclosureObj = null; + if (disclosures != null) { + disclosureObj = disclosures.get(key); + } + Object saltObj = salt.get(key); + Object newClaimObj = claim.get(key); + + if (saltObj instanceof Map) { + addSaltAndGetHash( + (HashMap) newClaimObj, + (HashMap) saltObj, + (HashMap) disclosureObj + ); + } else if (saltObj instanceof List) { + ArrayList disclosureObjList = null; + if (disclosureObj != null) { + disclosureObjList = (ArrayList) disclosureObj; + } + addSaltAndGetHashForList( + (ArrayList) newClaimObj, + (ArrayList) saltObj, + disclosureObjList + ); + } else { + addSaltByDisclose(claim, key, disclosureObj, saltObj, newClaimObj); + } + } + } + + private static void addSaltByDisclose( + Map claim, + String key, + Object disclosureObj, + Object saltObj, + Object newClaimObj + ) { + if (disclosureObj == null) { + if (!NOT_DISCLOSED.toString().equals(saltObj.toString())) { + claim.put( + key, + getFieldSaltHash(String.valueOf(newClaimObj), String.valueOf(saltObj)) + ); + } + } else if (NOT_DISCLOSED.toString().equals(disclosureObj.toString())) { + claim.put( + key, + getFieldSaltHash(String.valueOf(newClaimObj), String.valueOf(saltObj)) + ); + } + } + + private static void addSaltAndGetHashForList( + List claim, + List salt, + List disclosures + ) { + for (int i = 0; claim != null && i < claim.size(); i++) { + Object obj = claim.get(i); + Object saltObj = salt.get(i); + if (obj instanceof Map) { + Object disclosureObj = null; + if (disclosures != null) { + disclosureObj = disclosures.get(0); + } + addSaltAndGetHash((HashMap) obj, (HashMap) saltObj, (HashMap) disclosureObj); + } else if (obj instanceof List) { + ArrayList disclosureObjList = null; + if (disclosures != null) { + Object disclosureObj = disclosures.get(i); + if (disclosureObj != null) { + disclosureObjList = (ArrayList) disclosureObj; + } + } + addSaltAndGetHashForList( + (ArrayList) obj, + (ArrayList) saltObj, + disclosureObjList + ); + } + } + } + + /** + * Set all the values in a map to be null while preserving its key structure recursively. + * + * @param map the map + */ + public static void clearMap(Map map) { + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object mapObj = map.get(key); + if (mapObj instanceof Map) { + clearMap((HashMap) mapObj); + } else if (mapObj instanceof List) { + clearMapList((ArrayList) mapObj); + } else { + map.put(key, StringUtils.EMPTY); + } + } + } + + private static void clearMapList(ArrayList listObj) { + for (int i = 0; listObj != null && i < listObj.size(); i++) { + Object obj = listObj.get(i); + if (obj instanceof Map) { + clearMap((HashMap) obj); + } else if (obj instanceof List) { + clearMapList((ArrayList) obj); + } else { + listObj.set(i, StringUtils.EMPTY); + } + } + } + + /** + * Check the credential and proof of presentationE. + * + * @param presentationE the presentation + * @return return the check code + */ + public static ErrorCode checkPresentationEValid(PresentationE presentationE) { + if (presentationE == null || presentationE.getVerifiableCredential() == null + || presentationE.getVerifiableCredential().isEmpty() + || presentationE.getProof() == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (StringUtils.isEmpty(presentationE.getSignature())) { + return ErrorCode.CREDENTIAL_SIGNATURE_NOT_EXISTS; + } + return ErrorCode.SUCCESS; + } + + /** + * Check the validity of a given policy of PresentationPolicyE. + * + * @param presentationPolicyE the presentationPolicyE + * @return true if yes, false otherwise + */ + public static boolean checkPresentationPolicyEValid(PresentationPolicyE presentationPolicyE) { + return (presentationPolicyE != null + && presentationPolicyE.getPolicy() != null + && presentationPolicyE.getPolicy().size() != 0); + } + + /** + * Get per-field salted hash value. + * + * @param field the field value + * @param salt the salt value + * @return the hash value + */ + public static String getFieldSaltHash(String field, String salt) { + return DataToolUtils.hash(String.valueOf(field) + String.valueOf(salt)); + } + + /** + * remove credentialPojo not disclosure claimData with salt. + * + * @param credentialPojo credentialPojo + * @return claimData of remove not disclosure data + */ + public static Map getDisclosedClaim(CredentialPojo credentialPojo) { + if (credentialPojo == null + || !validClaimAndSaltForMap(credentialPojo.getClaim(), credentialPojo.getSalt())) { + logger.error("getDisclosuredClaimData failed, credentialPojo is null or " + + "claim and salt of credentialPojo not match "); + return null; + } + Map claimMap = credentialPojo.getClaim(); + Map newMap = DataToolUtils.clone((HashMap) claimMap); + Map saltMap = credentialPojo.getSalt(); + getDisclosureClaimData(saltMap, newMap); + return newMap; + } + + private static void getDisclosureClaimData( + Map saltMap, + Map claim + ) { + for (Map.Entry entry : saltMap.entrySet()) { + String saltKey = entry.getKey(); + Object saltV = entry.getValue(); + Object claimV = claim.get(saltKey); + if (saltV instanceof Map) { + getDisclosureClaimData((HashMap) saltV, (HashMap) claimV); + } else if (saltV instanceof List) { + getDisclosureClaimDataForList( + (ArrayList) saltV, + (ArrayList) claimV + ); + } else { + removeNotDisclosureData(claim, saltKey, saltV); + } + } + } + + /** + * remove credentialPojo not disclosure claimData with salt. + * + * @param any object + * @param credentialPojo credentialPojo + * @param presentationPolicyId the presentation Policy Id + * @return policy CPT object + */ + public static T getDisclosedClaimPojo( + CredentialPojo credentialPojo, + String presentationPolicyId) { + + ErrorCode errorCode = isCredentialPojoValid(credentialPojo); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + logger.error( + "[getDisclosedClaimPojo]The input credential is not a valid credential! " + + "errorCode is {}", + errorCode); + return null; + } + if (StringUtils.isEmpty(presentationPolicyId)) { + logger.error("[getDisclosedClaimPojo]The input presentation policy id is empty."); + return null; + } + Integer cptId = credentialPojo.getCptId(); + String pojoClass = new StringBuffer() + .append(ParamKeyConstant.POLICY_PACKAGE) + .append(ParamKeyConstant.CPT) + .append(cptId) + .append(ParamKeyConstant.POLICY) + .append(presentationPolicyId) + .toString(); + + Map claim = credentialPojo.getClaim(); + Object claimPojoData = null; + try { + claimPojoData = DataToolUtils.mapToObj(claim, Class.forName(pojoClass)); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + logger.error("[getDisclosedClaimPojo] Convert claim to POJO failed, Error msg:", e); + } catch (Exception e) { + logger.error("[getDisclosedClaimPojo] Convert claim to POJO failed, Exception msg:", e); + } + return (T) claimPojoData; + } + + private static void removeNotDisclosureData( + Map claim, + String saltKey, + Object saltV + ) { + if (!StringUtils.isBlank(saltV.toString()) + && (String.valueOf(saltV)).equals(NOT_DISCLOSED.toString())) { + claim.remove(saltKey); + } + } + + private static void getDisclosureClaimDataForList(List salt, List claim) { + for (int i = 0; claim != null && i < salt.size(); i++) { + Object saltObj = salt.get(i); + Object claimObj = claim.get(i); + if (saltObj instanceof Map) { + getDisclosureClaimData((HashMap) saltObj, (HashMap) claimObj); + } else if (saltObj instanceof List) { + getDisclosureClaimDataForList( + (ArrayList) saltObj, + (ArrayList) claimObj + ); + } + } + } + + /** + * valid claim and salt. + * + * @param claim claimMap + * @param salt saltMap + * @return boolean + */ + public static boolean validClaimAndSaltForMap( + Map claim, + Map salt) { + //检查是否为空 + if (claim == null || salt == null) { + return false; + } + //检查每个map里的key个数是否相同 + Set claimKeys = claim.keySet(); + Set saltKeys = salt.keySet(); + if (claimKeys.size() != saltKeys.size()) { + return false; + } + //检查key值是否一致 + for (Map.Entry entry : claim.entrySet()) { + String k = entry.getKey(); + Object claimV = entry.getValue(); + Object saltV = salt.get(k); + if (!salt.containsKey(k)) { + return false; + } + if (claimV instanceof Map) { + //递归检查 + if (!validClaimAndSaltForMap((HashMap) claimV, (HashMap) saltV)) { + return false; + } + } else if (claimV instanceof List) { + ArrayList claimValue = (ArrayList) claimV; + if (saltV instanceof ArrayList) { + ArrayList saltValue = (ArrayList) saltV; + if (!validClaimAndSaltForList(claimValue, saltValue)) { + return false; + } + } else { + continue; + } + } + } + return true; + } + + private static boolean validClaimAndSaltForList( + List claimList, + List saltList) { + //检查是否为空 + if (claimList == null || saltList == null) { + return false; + } + for (int i = 0; i < claimList.size(); i++) { + Object claimObj = claimList.get(i); + Object saltObj = saltList.get(i); + if (claimObj instanceof Map) { + if (!(saltObj instanceof Map)) { + return false; + } + if (!validClaimAndSaltForMap((HashMap) claimObj, (HashMap) saltObj)) { + return false; + } + } else if (claimObj instanceof List) { + if (!(saltObj instanceof List)) { + return false; + } + ArrayList claimObjV = (ArrayList) claimObj; + ArrayList saltObjV = (ArrayList) saltObj; + if (!validClaimAndSaltForList(claimObjV, saltObjV)) { + return false; + } + } + } + return true; + } + + /** + * Check the given CreateCredentialPojoArgs validity based on its input params. + * + * @param args CreateCredentialPojoArgs + * @return true if yes, false otherwise + */ + public static ErrorCode isCreateCredentialPojoArgsValid( + CreateCredentialPojoArgs args) { + if (args == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (args.getCptId() == null || args.getCptId().intValue() < 0) { + return ErrorCode.CPT_ID_ILLEGAL; + } + if (!WeIdUtils.isWeIdValid(args.getIssuer())) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + + if (args.getClaim() == null) { + return ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS; + } + ErrorCode errorCode = validDateExpired(args.getIssuanceDate(), args.getExpirationDate()); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return errorCode; + } + if (args.getWeIdAuthentication() != null + && !StringUtils.isEmpty(args.getWeIdAuthentication().getWeId()) + && !args.getWeIdAuthentication().getWeId().equalsIgnoreCase(args.getIssuer())) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + return isWeIdAuthenticationValid(args.getWeIdAuthentication()); + } + + /** + * Check WeIdAuthentication validity. + * + * @param callerAuth WeIdAuthentication + * @return true if yes, false otherwise + */ + public static ErrorCode isWeIdAuthenticationValid(WeIdAuthentication callerAuth) { + if (callerAuth == null + || callerAuth.getWeIdPrivateKey() == null + || StringUtils.isBlank(callerAuth.getWeIdPrivateKey().getPrivateKey()) + || StringUtils.isBlank(callerAuth.getAuthenticationMethodId())) { + return ErrorCode.ILLEGAL_INPUT; + } + if (!WeIdUtils.isWeIdValid(callerAuth.getWeId())) { + return ErrorCode.WEID_INVALID; + } + return ErrorCode.SUCCESS; + } + + private static ErrorCode validDateExpired(Long issuanceDate, Long expirationDate) { + if (issuanceDate != null && issuanceDate <= 0) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + if (expirationDate == null + || expirationDate.longValue() < 0 + || expirationDate.longValue() == 0) { + return ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL; + } + if (!DateUtils.isAfterCurrentTime(expirationDate)) { + return ErrorCode.CREDENTIAL_EXPIRED; + } + if (issuanceDate != null && expirationDate < issuanceDate) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + return ErrorCode.SUCCESS; + } + + /** + * Check the given CredentialPojo validity based on its input params. + * + * @param args CredentialPojo + * @return true if yes, false otherwise + */ + public static ErrorCode isCredentialPojoValid(CredentialPojo args) { + if (args == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (args.getCptId() == null || args.getCptId().intValue() < 0) { + return ErrorCode.CPT_ID_ILLEGAL; + } + if (!WeIdUtils.isWeIdValid(args.getIssuer())) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + if (args.getClaim() == null) { + return ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS; + } + if (args.getIssuanceDate() == null) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + ErrorCode errorCode = validDateExpired(args.getIssuanceDate(), args.getExpirationDate()); + if (errorCode.getCode() != ErrorCode.SUCCESS.getCode()) { + return errorCode; + } + ErrorCode contentResponseData = isCredentialContentValid(args); + if (ErrorCode.SUCCESS.getCode() != contentResponseData.getCode()) { + return contentResponseData; + } + return ErrorCode.SUCCESS; + } + + /** + * Check the given CredentialPojo content fields validity excluding metadata, based on its + * input. + * + * @param args CredentialPojo + * @return true if yes, false otherwise + */ + private static ErrorCode isCredentialContentValid(CredentialPojo args) { + String credentialId = args.getId(); + if (StringUtils.isEmpty(credentialId) || !CredentialUtils.isValidUuid(credentialId)) { + return ErrorCode.CREDENTIAL_ID_NOT_EXISTS; + } + String context = args.getContext(); + if (StringUtils.isEmpty(context)) { + return ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS; + } + if (CollectionUtils.isEmpty(args.getType())) { + return ErrorCode.CREDENTIAL_TYPE_IS_NULL; + } + Map proof = args.getProof(); + return isCredentialProofValid(proof); + } + + private static ErrorCode isCredentialProofValid(Map proof) { + if (proof == null) { + return ErrorCode.ILLEGAL_INPUT; + } + + String type = null; + if (proof.get(ParamKeyConstant.PROOF_TYPE) == null) { + return ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL; + } else { + type = String.valueOf(proof.get(ParamKeyConstant.PROOF_TYPE)); + if (!isCredentialProofTypeValid(type)) { + return ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL; + } + } + // Created is not obligatory + if (proof.get(ParamKeyConstant.PROOF_CREATED) == null) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } else { + Long created = Long.valueOf(String.valueOf(proof.get(ParamKeyConstant.PROOF_CREATED))); + if (created.longValue() <= 0) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + } + // Creator is not obligatory either + if (proof.get(ParamKeyConstant.PROOF_CREATOR) == null) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } else { + String creator = String.valueOf(proof.get(ParamKeyConstant.PROOF_CREATOR)); + //if (!StringUtils.isEmpty(creator) && !WeIdUtils.isWeIdValid(creator)) { + if (StringUtils.isEmpty(creator)) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + } + // If the Proof type is ECDSA or other signature based scheme, check signature + if (type.equalsIgnoreCase(CredentialProofType.ECDSA.getTypeName())) { + if (proof.get(ParamKeyConstant.PROOF_SIGNATURE) == null) { + return ErrorCode.CREDENTIAL_SIGNATURE_BROKEN; + } else { + String signature = String.valueOf(proof.get(ParamKeyConstant.PROOF_SIGNATURE)); + if (StringUtils.isEmpty(signature) + || !DataToolUtils.isValidBase64String(signature)) { + return ErrorCode.CREDENTIAL_SIGNATURE_BROKEN; + } + } + } + return ErrorCode.SUCCESS; + } + + private static boolean isCredentialProofTypeValid(String type) { + // Proof type must be one of the pre-defined types. + if (!StringUtils.isEmpty(type)) { + for (CredentialProofType proofType : CredentialConstant.CredentialProofType.values()) { + if (StringUtils.equalsIgnoreCase(type, proofType.getTypeName())) { + return true; + } + } + } + return false; + } + + /** + * check if the cpt can be used for zkp or not. + * + * @param cptJson the json schema of the CPT + * @return true if can be used for zkp, otherwise fales + */ + public static boolean isZkpCpt(String cptJson) { + + Map jsonSchemaMap = DataToolUtils + .deserialize(cptJson.trim(), HashMap.class); + if (jsonSchemaMap.containsKey(CredentialConstant.CPT_TYPE_KEY)) { + String cptType = String.valueOf(jsonSchemaMap.get(CredentialConstant.CPT_TYPE_KEY)); + if (StringUtils.equals(cptType, CptType.ZKP.getName().toString())) { + return true; + } + } + return false; + } + + /** + * Check if this CredentialPojo is Lite Credential. + * + * @param credential the credential + * @return true if yes, false otherwise + */ + public static boolean isLiteCredential(CredentialPojo credential) { + + List types = credential.getType(); + if (types.contains(CredentialType.LITE1.getName())) { + return true; + } + return false; + } +} diff --git a/src/main/java/com/webank/weid/util/CredentialUtils.java b/src/main/java/com/webank/weid/util/CredentialUtils.java index 3d150218..3014e777 100644 --- a/src/main/java/com/webank/weid/util/CredentialUtils.java +++ b/src/main/java/com/webank/weid/util/CredentialUtils.java @@ -1,102 +1,257 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.constant.*; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.CredentialConstant.CredentialProofType; import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.CredentialWrapper; import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; - import org.apache.commons.lang3.StringUtils; +import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32; + +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Pattern; /** * The Class CredentialUtils. * - * @author chaoxinhu 2018.10 + * @author chaoxinhu 2019.1 */ public final class CredentialUtils { /** - * Concat all fields of Credential info. + * Concat all fields of Credential info, without Proof, in Json format. This should be invoked + * when calculating Credential Signature as the raw message. Return null if credential format is + * illegal. The Json return value satisfy the following format: 1. Keys are dict-ordered; 2. + * Claim comes from standard getClaimHash() to support selective disclosure; 3. Compact output + * without any extra space or linebreaks, to avoid different Json format beautification. * - * @param arg target Credential object + * @param credential target Credential object + * @param disclosures disclosures of the credential * @return Hash value in String. */ - public static String getCredentialFields(Credential arg) { - if (arg == null - || arg.getCptId() == null - || arg.getIssuranceDate() == null - || arg.getExpirationDate() == null) { + public static String getCredentialThumbprintWithoutSig( + Credential credential, + Map disclosures) { + try { + Credential rawCredential = copyCredential(credential); + rawCredential.setProof(null); + return getCredentialThumbprint(rawCredential, disclosures); + } catch (Exception e) { return StringUtils.EMPTY; } - String rawData = - arg.getContext() - + WeIdConstant.PIPELINE - + arg.getId() - + WeIdConstant.PIPELINE - + Integer.toString(arg.getCptId()) - + WeIdConstant.PIPELINE - + arg.getIssuer() - + WeIdConstant.PIPELINE - + arg.getIssuranceDate().toString() - + WeIdConstant.PIPELINE - + arg.getExpirationDate().toString() - + WeIdConstant.PIPELINE - + arg.getClaim(); - return rawData; } /** - * Craft a non-masquerade hash which contains all fields of Credential info. + * Check if the two credentials are equal. Will traverse each field. * - * @param arg the arg + * @param credOld first credential + * @param credNew second credential + * @return true if yes, false otherwise + */ + public static boolean isEqual(Credential credOld, Credential credNew) { + if (credOld == null && credNew == null) { + return true; + } + if (credOld == null || credNew == null) { + return false; + } + return credOld.getHash().equalsIgnoreCase(credNew.getHash()) + && credOld.getCptId().equals(credNew.getCptId()) + && credOld.getExpirationDate().equals(credNew.getExpirationDate()) + && credOld.getProof().equals(credNew.getProof()) + && credOld.getContext().equalsIgnoreCase(credNew.getContext()) + && credOld.getId().equalsIgnoreCase(credNew.getId()) + && credOld.getIssuanceDate().equals(credNew.getIssuanceDate()) + && credOld.getIssuer().equalsIgnoreCase(credNew.getIssuer()); + } + + /** + * Build the credential Proof. + * + * @param credential the credential + * @param privateKey private key decimal + * @param disclosureMap the disclosureMap + * @return the Proof structure + */ + public static Map buildCredentialProof( + Credential credential, + String privateKey, + Map disclosureMap) { + Map proof = new HashMap<>(); + proof.put(ParamKeyConstant.PROOF_CREATED, credential.getIssuanceDate().toString()); + proof.put(ParamKeyConstant.PROOF_CREATOR, credential.getIssuer()); + proof.put(ParamKeyConstant.PROOF_TYPE, getDefaultCredentialProofType()); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, + getCredentialSignature(credential, privateKey, disclosureMap)); + return proof; + } + + /** + * A clean deep copy method of a Credential which pays special attention on Map object. todo: + * preserve the claim key order + * + * @param credential target Credential object + * @return new credential + */ + public static Credential copyCredential(Credential credential) { + Credential ct = new Credential(); + ct.setContext(credential.getContext()); + + Map originalProof = credential.getProof(); + if (originalProof != null) { + Map proof = DataToolUtils + .deserialize(DataToolUtils.serialize(originalProof), HashMap.class); + ct.setProof(proof); + } + Map originalClaim = credential.getClaim(); + if (originalClaim != null) { + Map claim = DataToolUtils + .deserialize(DataToolUtils.serialize(originalClaim), HashMap.class); + ct.setClaim(claim); + } + + ct.setIssuanceDate(credential.getIssuanceDate()); + ct.setCptId(credential.getCptId()); + ct.setExpirationDate(credential.getExpirationDate()); + ct.setIssuer(credential.getIssuer()); + ct.setId(credential.getId()); + return ct; + } + + + /** + * A clean deep copy method of a CredentialPojo which pays special attention on Map object. + * + * @param credentialPojo target CredentialPojo object + * @return new credentialPojo + */ + public static CredentialPojo copyCredential(CredentialPojo credentialPojo) { + CredentialPojo cpj = new CredentialPojo(); + cpj.setContext(credentialPojo.getContext()); + cpj.setIssuanceDate(credentialPojo.getIssuanceDate()); + cpj.setCptId(credentialPojo.getCptId()); + cpj.setExpirationDate(credentialPojo.getExpirationDate()); + cpj.setIssuer(credentialPojo.getIssuer()); + cpj.setId(credentialPojo.getId()); + + Map originalProof = credentialPojo.getProof(); + if (originalProof != null) { + Map proof = DataToolUtils + .deserialize(DataToolUtils.serialize(originalProof), HashMap.class); + cpj.setProof(proof); + } + Map originalClaim = credentialPojo.getClaim(); + if (originalClaim != null) { + Map claim = DataToolUtils + .deserialize(DataToolUtils.serialize(originalClaim), HashMap.class); + cpj.setClaim(claim); + } + List originalType = credentialPojo.getType(); + if (originalType != null) { + List type = new ArrayList<>(originalType.size()); + if (originalType.size() > 0) { + for (String originalTypeItem : originalType) { + type.add(originalTypeItem); + } + } + cpj.setType(type); + } + + return cpj; + } + + /** + * Concat all fields of Credential info, with signature. This should be invoked when calculating + * credential hash value for Credential Evidence. Return null if credential format is illegal. + * The Json return value satisfy the same standard as the thumbprint without signature. + * + * @param credential target Credential object + * @param disclosures the disclosure map * @return Hash value in String. */ - public static String getCredentialFields(VerifyCredentialArgs arg) { - if (arg == null) { + public static String getCredentialThumbprint( + Credential credential, + Map disclosures) { + try { + Map credMap = DataToolUtils.objToMap(credential); + String claimHash = getClaimHash(credential, disclosures); + credMap.put(ParamKeyConstant.CLAIM, claimHash); + return DataToolUtils.mapToCompactJson(credMap); + } catch (Exception e) { return StringUtils.EMPTY; } - return getCredentialFields(extractCredentialResult(arg)); } /** - * Get default Credential Context String. + * Get the claim hash. This is irrelevant to selective disclosure. * - * @return Context value in String. + * @param credential Credential + * @param disclosures Disclosure Map + * @return the unique claim hash value */ - public static String getDefaultCredentialContext() { - return WeIdConstant.DEFAULT_CERTIFICATE_CONTEXT; + public static String getClaimHash(Credential credential, Map disclosures) { + + Map claim = credential.getClaim(); + Map claimHashMap = new HashMap<>(claim); + Map disclosureMap; + + if (disclosures == null) { + disclosureMap = new HashMap<>(claim); + for (Map.Entry entry : disclosureMap.entrySet()) { + disclosureMap.put( + entry.getKey(), + CredentialFieldDisclosureValue.DISCLOSED.getStatus() + ); + } + } else { + disclosureMap = disclosures; + } + + for (Map.Entry entry : disclosureMap.entrySet()) { + claimHashMap.put(entry.getKey(), getFieldHash(claimHashMap.get(entry.getKey()))); + } + + List> list = new ArrayList>( + claimHashMap.entrySet() + ); + Collections.sort(list, new Comparator>() { + + @Override + public int compare(Entry o1, Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + } + }); + + StringBuffer hash = new StringBuffer(); + for (Map.Entry en : list) { + hash.append(en.getKey()).append(en.getValue()); + } + return hash.toString(); } /** - * Extract Credential from VerifyCredentialArgs. + * convert a field to hash. * - * @param arg the arg - * @return Credential + * @param field which will be converted to hash. + * @return hash value. */ - public static Credential extractCredentialResult(VerifyCredentialArgs arg) { - if (arg == null) { - return null; - } - Credential credential = arg.getCredential(); - return credential; + public static String getFieldHash(Object field) { + return DataToolUtils.hash(String.valueOf(field)); + } + + /** + * Get default Credential Context String. + * + * @return Context value in String. + */ + public static String getDefaultCredentialContext() { + return CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT; } /** @@ -112,8 +267,219 @@ public static CreateCredentialArgs extractCredentialMetadata(Credential arg) { CreateCredentialArgs generateCredentialArgs = new CreateCredentialArgs(); generateCredentialArgs.setCptId(arg.getCptId()); generateCredentialArgs.setIssuer(arg.getIssuer()); + generateCredentialArgs.setIssuanceDate(arg.getIssuanceDate()); generateCredentialArgs.setExpirationDate(arg.getExpirationDate()); generateCredentialArgs.setClaim(arg.getClaim()); return generateCredentialArgs; } + + /** + * Create the signature for this Credential. The original signature value, will be set empty + * whether its original value is already empty or not. The rawData input for the signature + * creation is the credential thumbprint result based on an empty signature value filled in. + * + * @param credential target credential object + * @param privateKey decimal + * @param disclosureMap the disclosure map + * @return the String signature value + */ + public static String getCredentialSignature(Credential credential, + String privateKey, Map disclosureMap) { + String rawData = CredentialUtils + .getCredentialThumbprintWithoutSig(credential, disclosureMap); + return DataToolUtils.SigBase64Serialization(DataToolUtils.signToRsvSignature(rawData, privateKey)); + } + + /** + * Create a full Credential Hash for a Credential based on all its fields. This should be + * invoked when getting Credential Evidence. Please note: the result is a String with fixed + * length 66 bytes including the first two bytes ("0x") and 64 bytes Hash value. + * + * @param arg the args + * @return Hash in byte array + */ + public static String getCredentialHash(Credential arg) { + String rawData = getCredentialThumbprint(arg, null); + if (StringUtils.isEmpty(rawData)) { + return StringUtils.EMPTY; + } + return DataToolUtils.hash(rawData); + } + + /** + * Create a full CredentialWrapper Hash for a Credential based on all its fields, which is + * resistant to selective disclosure. + * + * @param arg the args + * @return Hash in byte array + */ + public static String getCredentialWrapperHash(CredentialWrapper arg) { + String rawData = getCredentialThumbprint(arg.getCredential(), arg.getDisclosure()); + if (StringUtils.isEmpty(rawData)) { + return StringUtils.EMPTY; + } + return DataToolUtils.hash(rawData); + } + + /** + * Convert a Credential ID to a Bytes32 object. The "-" connector will be removed. + * + * @param id the Credential id + * @return a Bytes32 object + */ + public static Bytes32 convertCredentialIdToBytes32(String id) { + if (!isValidUuid(id)) { + return new Bytes32(new byte[32]); + } + String mergedId = id.replaceAll(WeIdConstant.UUID_SEPARATOR, StringUtils.EMPTY); + byte[] uuidBytes = mergedId.getBytes(StandardCharsets.UTF_8); + return com.webank.weid.blockchain.util.DataToolUtils.bytesArrayToBytes32(uuidBytes); + } + + /** + * Check whether the given String is a valid UUID. + * + * @param id the Credential id + * @return true if yes, false otherwise + */ + public static boolean isValidUuid(String id) { + Pattern p = Pattern.compile(WeIdConstant.UUID_PATTERN); + return p.matcher(id).matches(); + } + + /** + * Check the given CreateCredentialArgs validity based on its input params. + * + * @param args CreateCredentialArgs + * @return true if yes, false otherwise + */ + public static ErrorCode isCreateCredentialArgsValid( + CreateCredentialArgs args) { + if (args == null) { + return ErrorCode.ILLEGAL_INPUT; + } + if (args.getCptId() == null || args.getCptId().intValue() < 0) { + return ErrorCode.CPT_ID_ILLEGAL; + } + if (!WeIdUtils.isWeIdValid(args.getIssuer())) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + Long issuanceDate = args.getIssuanceDate(); + if (issuanceDate != null && issuanceDate <= 0) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + Long expirationDate = args.getExpirationDate(); + if (expirationDate == null + || expirationDate.longValue() < 0 + || expirationDate.longValue() == 0) { + return ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL; + } + if (!DateUtils.isAfterCurrentTime(expirationDate)) { + return ErrorCode.CREDENTIAL_EXPIRED; + } + if (issuanceDate != null && expirationDate < issuanceDate) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + if (args.getClaim() == null || args.getClaim().isEmpty()) { + return ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS; + } + return ErrorCode.SUCCESS; + } + + /** + * Check the given Credential validity based on its input params. + * + * @param args Credential + * @return true if yes, false otherwise + */ + public static ErrorCode isCredentialValid(Credential args) { + if (args == null) { + return ErrorCode.ILLEGAL_INPUT; + } + CreateCredentialArgs createCredentialArgs = extractCredentialMetadata(args); + ErrorCode metadataResponseData = isCreateCredentialArgsValid(createCredentialArgs); + if (ErrorCode.SUCCESS.getCode() != metadataResponseData.getCode()) { + return metadataResponseData; + } + ErrorCode contentResponseData = isCredentialContentValid(args); + if (ErrorCode.SUCCESS.getCode() != contentResponseData.getCode()) { + return contentResponseData; + } + return ErrorCode.SUCCESS; + } + + /** + * Check the given Credential content fields validity excluding metadata, based on its input. + * + * @param args Credential + * @return true if yes, false otherwise + */ + public static ErrorCode isCredentialContentValid(Credential args) { + String credentialId = args.getId(); + if (StringUtils.isEmpty(credentialId) || !CredentialUtils.isValidUuid(credentialId)) { + return ErrorCode.CREDENTIAL_ID_NOT_EXISTS; + } + String context = args.getContext(); + if (StringUtils.isEmpty(context)) { + return ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS; + } + Long issuanceDate = args.getIssuanceDate(); + if (issuanceDate == null) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + if (issuanceDate.longValue() > args.getExpirationDate().longValue()) { + return ErrorCode.CREDENTIAL_EXPIRED; + } + Map proof = args.getProof(); + return isCredentialProofValid(proof); + } + + private static ErrorCode isCredentialProofValid(Map proof) { + if (proof == null) { + return ErrorCode.ILLEGAL_INPUT; + } + String type = proof.get(ParamKeyConstant.PROOF_TYPE); + if (!isCredentialProofTypeValid(type)) { + return ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL; + } + // Created is not obligatory + Long created = Long.valueOf(proof.get(ParamKeyConstant.PROOF_CREATED)); + if (created.longValue() <= 0) { + return ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL; + } + // Creator is not obligatory either + String creator = proof.get(ParamKeyConstant.PROOF_CREATOR); + if (!StringUtils.isEmpty(creator) && !WeIdUtils.isWeIdValid(creator)) { + return ErrorCode.CREDENTIAL_ISSUER_INVALID; + } + // If the Proof type is ECDSA or other signature based scheme, check signature + if (type.equalsIgnoreCase(CredentialProofType.ECDSA.getTypeName())) { + String signature = proof.get(ParamKeyConstant.CREDENTIAL_SIGNATURE); + if (StringUtils.isEmpty(signature) || !DataToolUtils.isValidBase64String(signature)) { + return ErrorCode.CREDENTIAL_SIGNATURE_BROKEN; + } + } + return ErrorCode.SUCCESS; + } + + /** + * Get default Credential Credential Proof Type String. + * + * @return Context value in String. + */ + public static String getDefaultCredentialProofType() { + return CredentialConstant.CredentialProofType.ECDSA.getTypeName(); + } + + private static boolean isCredentialProofTypeValid(String type) { + // Proof type must be one of the pre-defined types. + if (!StringUtils.isEmpty(type)) { + for (CredentialProofType proofType : CredentialConstant.CredentialProofType.values()) { + if (StringUtils.equalsIgnoreCase(type, proofType.getTypeName())) { + return true; + } + } + } + return false; + } } diff --git a/src/main/java/com/webank/weid/util/DataDriverUtils.java b/src/main/java/com/webank/weid/util/DataDriverUtils.java new file mode 100644 index 00000000..088f34c4 --- /dev/null +++ b/src/main/java/com/webank/weid/util/DataDriverUtils.java @@ -0,0 +1,91 @@ +package com.webank.weid.util; + +import com.webank.weid.suite.persistence.DefaultValue; +import io.ipfs.api.IPFS; +import io.ipfs.api.MerkleNode; +import io.ipfs.api.NamedStreamable; +import io.ipfs.multihash.Multihash; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Driver util + * + * @author 刘家辉 + * @date 2023/08/26 + */ +public class DataDriverUtils { + /** + * Easy to retrieve the desired value object from the Default Value + * + * @param value 价值 + * @param clazz clazz + * @return {@link T} + */ + public static T decodeValueForNeedObj(String value, Class clazz){ + DefaultValue data = DataToolUtils.deserialize( + value, DefaultValue.class); + return DataToolUtils.deserialize(data.getData(), clazz); + } + + /** + * Easy to retrieve the desired List object from the Default Value + * + * @param values 值 + * @param clazz clazz + * @return {@link List}<{@link T}> + */ + public List decodeValueToNeedListObj (List values, Class clazz){ + List list = new ArrayList(); + for(String value:values ){ + list.add(decodeValueForNeedObj(value,clazz)); + } + return list; + } + + /** + * Easy to retrieve the desired value json from the Default Value + * + * @param values 值 + * @return {@link List}<{@link String}> + */ + public static List decodeValueToNeedListJson(List values){ + List list = new ArrayList<>(); + for(String value:values ){ + list.add(DataToolUtils.deserialize( + value, DefaultValue.class).getData()); + } + return list; + } + + /** + * upload to ipfs + * + * @param ipfs ipf + * @param data 数据 + * @return {@link String} + * @throws IOException ioexception + */ + public static String uploadIpfs(IPFS ipfs, byte[] data) throws IOException { + NamedStreamable.ByteArrayWrapper file = new NamedStreamable.ByteArrayWrapper(data); + MerkleNode addResult = null; + addResult = ipfs.add(file).get(0); + return addResult.hash.toString(); + } + + /** + * download from ipfs + * + * @param ipfs ipf + * @param hash 哈希 + * @return {@link String} + * @throws IOException ioexception + */ + public static String downloadIpfs(IPFS ipfs,String hash) throws IOException { + byte[] data; + data = ipfs.cat(Multihash.fromBase58(hash)); + return DataToolUtils.bytesToStr(data); + } +} diff --git a/src/main/java/com/webank/weid/util/DataToolUtils.java b/src/main/java/com/webank/weid/util/DataToolUtils.java new file mode 100644 index 00000000..a513726a --- /dev/null +++ b/src/main/java/com/webank/weid/util/DataToolUtils.java @@ -0,0 +1,1409 @@ + +package com.webank.weid.util; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.networknt.schema.SpecVersion.VersionFlag; +import com.networknt.schema.ValidationMessage; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.protocol.base.AuthenticationProperty; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.protocol.cpt.RawCptSchema; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.response.RsvSignature; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Base64; +import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32; +import org.fisco.bcos.sdk.abi.datatypes.generated.Uint8; +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.crypto.signature.ECDSASignatureResult; +import org.fisco.bcos.sdk.crypto.signature.SM2SignatureResult; +import org.fisco.bcos.sdk.crypto.signature.SignatureResult; +import org.fisco.bcos.sdk.model.CryptoType; +import org.fisco.bcos.sdk.utils.Numeric; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.math.BigInteger; +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Pattern; + +/** + * 数据工具类. + * + * @author tonychen 2019年4月23日 + */ +public final class DataToolUtils { + + private static final Logger logger = LoggerFactory.getLogger(DataToolUtils.class); + private static final String SEPARATOR_CHAR = "-"; + //private static ObjectMapper objectMapper = new ObjectMapper(); + + /** + * default salt length. + */ + private static final String DEFAULT_SALT_LENGTH = "5"; + + private static final int SERIALIZED_SIGNATUREDATA_LENGTH = 65; + + private static final int radix = 10; + + private static final String TO_JSON = "toJson"; + + private static final String FROM_JSON = "fromJson"; + + private static final String KEY_CREATED = "created"; + + private static final String KEY_ISSUANCEDATE = "issuanceDate"; + + private static final String KEY_EXPIRATIONDATE = "expirationDate"; + + private static final String KEY_CLAIM = "claim"; + + private static final String KEY_FROM_TOJSON = "$from"; + + private static final List CONVERT_UTC_LONG_KEYLIST = new ArrayList<>(); + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + //private static final ObjectWriter OBJECT_WRITER; + //private static final ObjectReader OBJECT_READER; + private static final ObjectWriter OBJECT_WRITER_UN_PRETTY_PRINTER; + + private static final com.networknt.schema.JsonSchemaFactory JSON_SCHEMA_FACTORY; + + public static final String deployStyle = PropertyUtils.getProperty("deploy.style"); + + //Todo:后面把两个配置文件的cryptoType合成一个,只放在weidentity.properties文件 + public static int cryptoType = Integer.parseInt(PropertyUtils.getProperty("crypto.type")); + + public static final CryptoSuite cryptoSuite = new CryptoSuite(Integer.parseInt(PropertyUtils.getProperty("crypto.type"))); + /** + * use this to create key pair of v2 or v3 + * WARN: create keyPair must use BigInteger of privateKey or decimal String of privateKey + */ + static { + // sort by letter + OBJECT_MAPPER.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); + // when map is serialization, sort by key + OBJECT_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + // ignore mismatched fields + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + OBJECT_MAPPER.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + // use field for serialize and deSerialize + OBJECT_MAPPER.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE); + OBJECT_MAPPER.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE); + OBJECT_MAPPER.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + + OBJECT_WRITER_UN_PRETTY_PRINTER = OBJECT_MAPPER.writer(); + + CONVERT_UTC_LONG_KEYLIST.add(KEY_CREATED); + CONVERT_UTC_LONG_KEYLIST.add(KEY_ISSUANCEDATE); + CONVERT_UTC_LONG_KEYLIST.add(KEY_EXPIRATIONDATE); + + //OBJECT_WRITER = OBJECT_MAPPER.writer().withDefaultPrettyPrinter(); + //OBJECT_READER = OBJECT_MAPPER.reader(); + + JSON_SCHEMA_FACTORY = com.networknt.schema.JsonSchemaFactory.getInstance(VersionFlag.V4); + + if (deployStyle.equals("blockchain")) { + cryptoType = com.webank.weid.blockchain.util.DataToolUtils.cryptoType; + } + + } + + /** + * generate random string. + * + * @return random string + */ + public static String getRandomSalt() { + + String length = PropertyUtils.getProperty("salt.length", DEFAULT_SALT_LENGTH); + int saltLength = Integer.valueOf(length); + String salt = RandomStringUtils.random(saltLength, true, true); + return salt; + } + + /** + * Sha 3. + * + * @param input the input + * @return the string + */ + public static String hash(String input) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.hash(input); + } else { + // default database + return Numeric.toHexString(hash(input.getBytes(StandardCharsets.UTF_8))); + } + } + + /** + * Sha 3. + * + * @param input the input + * @return the byte[] + */ + public static byte[] hash(byte[] input) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.hash(input); + } else { + // default database + return cryptoSuite.hash(input); + } + } + + public static String getHash(String hexInput) { + return hash(hexInput); + } + + + /** + * serialize a class instance to Json String. + * + * @param object the class instance to serialize + * @param the type of the element + * @return JSON String + */ + public static String serialize(T object) { + Writer write = new StringWriter(); + try { + OBJECT_MAPPER.writeValue(write, object); + } catch (JsonGenerationException e) { + logger.error("JsonGenerationException when serialize object to json", e); + } catch (JsonMappingException e) { + logger.error("JsonMappingException when serialize object to json", e); + } catch (IOException e) { + logger.error("IOException when serialize object to json", e); + } + return write.toString(); + } + + + /** + * Check whether the String is a valid hash. + * + * @param hashValue hash in String + * @return true if yes, false otherwise + */ + public static boolean isValidHash(String hashValue) { + return !StringUtils.isEmpty(hashValue) + && Pattern.compile(WeIdConstant.HASH_VALUE_PATTERN).matcher(hashValue).matches(); + } + + /** + * deserialize a JSON String to an class instance. + * + * @param json json string + * @param clazz Class.class + * @param the type of the element + * @return class instance + */ + public static T deserialize(String json, Class clazz) { + Object object = null; + try { + if (isValidFromToJson(json)) { + logger.error("this jsonString is converted by toJson(), " + + "please use fromJson() to deserialize it"); + throw new DataTypeCastException("deserialize json to Object error"); + } + object = OBJECT_MAPPER.readValue(json, TypeFactory.rawClass(clazz)); + } catch (JsonParseException e) { + logger.error("JsonParseException when deserialize json to object", e); + throw new DataTypeCastException(e); + } catch (JsonMappingException e) { + logger.error("JsonMappingException when deserialize json to object", e); + throw new DataTypeCastException(e); + } catch (IOException e) { + logger.error("IOException when deserialize json to object", e); + throw new DataTypeCastException(e); + } + return (T) object; + } + + /** + * deserialize a JSON String to List. + * + * @param json json string + * @param clazz Class.class + * @param the type of the element + * @return class instance + */ + public static List deserializeToList(String json, Class clazz) { + List object = null; + try { + JavaType javaType = + OBJECT_MAPPER.getTypeFactory() + .constructParametricType(ArrayList.class, TypeFactory.rawClass(clazz)); + object = OBJECT_MAPPER.readValue(json, javaType); + } catch (JsonParseException e) { + logger.error("JsonParseException when serialize object to json", e); + throw new DataTypeCastException(e); + } catch (JsonMappingException e) { + logger.error("JsonMappingException when serialize object to json", e); + new DataTypeCastException(e); + } catch (IOException e) { + logger.error("IOException when serialize object to json", e); + } + return object; + } + + /** + * Object to Json String. + * + * @param obj Object + * @return String + */ + public static String objToJsonStrWithNoPretty(Object obj) { + + try { + return OBJECT_WRITER_UN_PRETTY_PRINTER.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new DataTypeCastException(e); + } + } + + /** + * readLocalJson + * @return {@link Object} + * @throws IOException ioexception + */ + public static Map readFromLocal(String path) throws IOException { + try { + File jsonFile = new File(path); + return OBJECT_MAPPER.readValue(jsonFile, new TypeReference>() { + }); + }catch (FileNotFoundException e){ + Map map = new HashMap<>(); + String[] parts = path.split("/"); + map.put("tableName",parts[2]); + writeInLocal(path,map); + readFromLocal(path); + } + return null; + + } + + /** + * write json in local + * @param path 路径 + * @param obj obj + * @return int + * @throws IOException ioexception + */ + public static int writeInLocal(String path,Object obj) throws IOException { + File jsonFile = new File(path); + OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValue(jsonFile, obj); + return 0; + } + + /** + * turn bytes to obj + * + * @param bytes 字节 + * @return {@link String} + * @throws IOException ioexception + */ + public static String bytesToStr(byte[] bytes) throws IOException { + return OBJECT_MAPPER.readTree(bytes).toPrettyString(); + } + + /** + * Convert a Map to compact Json output, with keys ordered. Use Jackson JsonNode toString() to + * ensure key order and compact output. + * + * @param map input map + * @return JsonString + * @throws Exception IOException + */ + public static String mapToCompactJson(Map map) throws Exception { + return OBJECT_MAPPER.readTree(serialize(map)).toString(); + } + + /** + * Convert a Map to compact Json output, with keys ordered. Use Jackson JsonNode toString() to + * ensure key order and compact output. + * + * @param map input map + * @return JsonString + * @throws Exception IOException + */ + public static String stringMapToCompactJson(Map map) throws Exception { + return OBJECT_MAPPER.readTree(serialize(map)).toString(); + } + + /** + * Convert a POJO to Map. + * + * @param object POJO + * @return Map + * @throws Exception IOException + */ + public static Map objToMap(Object object) throws Exception { + JsonNode jsonNode = OBJECT_MAPPER.readTree(serialize(object)); + return (HashMap) OBJECT_MAPPER.convertValue(jsonNode, HashMap.class); + } + + /** + * Convert a MAP to POJO. + * + * @param map the input data + * @param the type of the element + * @param clazz the output class type + * @return object in T type + * @throws Exception IOException + */ + public static T mapToObj(Map map, Class clazz) throws Exception { + final T pojo = (T) OBJECT_MAPPER.convertValue(map, clazz); + return pojo; + } + + /** + * 对象深度复制(对象必须是实现了Serializable接口). + * + * @param obj pojo + * @param the type of the element + * @return Object clonedObj + */ + @SuppressWarnings("unchecked") + public static T clone(T obj) { + T clonedObj = null; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(obj); + oos.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + clonedObj = (T) ois.readObject(); + ois.close(); + } catch (Exception e) { + logger.error("clone object has error.", e); + } + return clonedObj; + } + + /** + * Load Json Object. Can be used to return both Json Data and Json Schema. + * + * @param jsonString the json string + * @return JsonNode + * @throws JsonProcessingException parse json fail + */ + public static JsonNode loadJsonObject(String jsonString) throws JsonProcessingException { + return OBJECT_MAPPER.readTree(jsonString); + + } + + /** + * load json from resource + * @param path class path file path + * @return json node + * @throws IOException load error + */ + public static JsonNode loadJsonObjectFromResource(String path) throws IOException { + try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path)) { + if (inputStream == null) { + throw new DataTypeCastException("open path to inputStream get null!"); + } + return OBJECT_MAPPER.readTree(inputStream); + } + } + + /** + * load json from file + * @param file file of json + * @return json node + * @throws IOException file not found + */ + public static JsonNode loadJsonObjectFromFile(File file) throws IOException { + try (FileInputStream inputStream = new FileInputStream(file)) { + return OBJECT_MAPPER.readTree(inputStream); + } catch (FileNotFoundException e) { + logger.error("file not found when load jsonObject:{}", file.getPath()); + throw new DataTypeCastException(e); + } + } + + + /** + * Validate Json Data versus Json Schema. + * + * @param jsonData the json data + * @param jsonSchema the json schema + * @return empty if yes, not empty otherwise + * @throws Exception the exception + */ + public static Set checkJsonVersusSchema(String jsonData, String jsonSchema) + throws Exception { + JsonNode jsonDataNode = loadJsonObject(jsonData); + JsonNode jsonSchemaNode = loadJsonObject(jsonSchema); + // use new validator + com.networknt.schema.JsonSchema schema = JSON_SCHEMA_FACTORY.getSchema(jsonSchemaNode); + Set report = schema.validate(jsonDataNode); + if (report.size() == 0) { + logger.info(report.toString()); + } else { + Iterator it = report.iterator(); + StringBuffer errorMsg = new StringBuffer(); + while (it.hasNext()) { + ValidationMessage msg = it.next(); + errorMsg.append(msg.getCode()).append(":").append(msg.getMessage()); + } + logger.error("Json schema validator failed, error: {}", errorMsg.toString()); + } + return report; +// JsonSchema schema = JsonSchemaFactory.byDefault().getJsonSchema(jsonSchemaNode); +// ProcessingReport report = schema.validate(jsonDataNode); +// if (report.isSuccess()) { +// logger.info(report.toString()); +// } else { +// Iterator it = report.iterator(); +// StringBuffer errorMsg = new StringBuffer(); +// while (it.hasNext()) { +// errorMsg.append(it.next().getMessage()); +// } +// logger.error("Json schema validator failed, error: {}", errorMsg.toString()); +// } +// return report; + } + + /** + * Validate Json Schema format validity. + * + * @param jsonSchema the json schema + * @return true if yes, false otherwise + * @throws IOException Signals that an I/O exception has occurred. + */ +// public static boolean isValidJsonSchema(String jsonSchema) { +// return JsonSchemaFactory +// .byDefault() +// .getSyntaxValidator() +// .schemaIsValid(loadJsonObject(jsonSchema)); +// } + + /** + * validate Cpt Json Schema validity . + * + * @param cptJsonSchema the cpt json schema + * @return true, if is cpt json schema valid + * @throws IOException Signals that an I/O exception has occurred. + */ + public static boolean isCptJsonSchemaValid(String cptJsonSchema) throws IOException { + return StringUtils.isNotEmpty(cptJsonSchema) +// && isValidJsonSchema(cptJsonSchema) + && cptJsonSchema.length() <= WeIdConstant.JSON_SCHEMA_MAX_LENGTH; + } + + /** + * Check if this json string is in valid format. + * + * @param json Json string + * @return true if yes, false otherwise + */ + public static boolean isValidJsonStr(String json) { + if (StringUtils.isEmpty(json)) { + return false; + } + try { + final ObjectMapper mapper = new ObjectMapper(); + mapper.readTree(json); + return true; + } catch (IOException e) { + return false; + } + } + + /** + * create new cpt json schema. + * + * @param args Map + * @return String + */ + public static String cptSchemaToString(CptMapArgs args) { + + Map cptJsonSchema = args.getCptJsonSchema(); + Map cptJsonSchemaNew = new HashMap(); + cptJsonSchemaNew.put(JsonSchemaConstant.SCHEMA_KEY, JsonSchemaConstant.SCHEMA_VALUE); + cptJsonSchemaNew.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_OBJECT); + cptJsonSchemaNew.putAll(cptJsonSchema); + String cptType = args.getCptType().getName(); + cptJsonSchemaNew.put(CredentialConstant.CPT_TYPE_KEY, cptType); + return DataToolUtils.serialize(cptJsonSchemaNew); + } + + + /** + * Secp256k1 sign to Signature. + * + * @param rawData original raw data + * @param privateKey decimal + * @return SignatureData for signature value + */ + public static RsvSignature signToRsvSignature(String rawData, String privateKey) { + if (deployStyle.equals("blockchain")) { + return RsvSignature.fromBlockChain(com.webank.weid.blockchain.util.DataToolUtils.signToRsvSignature(rawData, privateKey)); + } else { + // default database + String messageHash = hash(rawData); + return sign(messageHash, privateKey); + } + } + + public static RsvSignature sign(String messageHash, String privateKey) { + CryptoKeyPair cryptoKeyPair = cryptoSuite.getKeyPairFactory().createKeyPair(new BigInteger(privateKey)); + RsvSignature rsvSignature = new RsvSignature(); + SignatureResult signatureResult = cryptoSuite.sign(messageHash, cryptoKeyPair); + Bytes32 R = new Bytes32(signatureResult.getR()); + rsvSignature.setR(R); + Bytes32 S = new Bytes32(signatureResult.getS()); + rsvSignature.setS(S); + if(cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE){ + ECDSASignatureResult ecdsaSignatureResult = new ECDSASignatureResult(signatureResult.convertToString()); + rsvSignature.setV(new Uint8(BigInteger.valueOf(ecdsaSignatureResult.getV()))); + } else { + rsvSignature.setV(new Uint8(0)); + } + return rsvSignature; + } + + /** + * Serialize secp256k1 signature into base64 encoded, in R, S, V (0, 1) format. + * + * @param sigData secp256k1 signature (v = 0,1) + * @return base64 string + */ + public static String SigBase64Serialization( + RsvSignature sigData) { + byte[] sigBytes = new byte[65]; + sigBytes[64] = sigData.getV().getValue().byteValue(); + System.arraycopy(sigData.getR().getValue(), 0, sigBytes, 0, 32); + System.arraycopy(sigData.getS().getValue(), 0, sigBytes, 32, 32); + return new String(base64Encode(sigBytes), StandardCharsets.UTF_8); + } + + /** + * De-Serialize secp256k1 signature base64 encoded string, in R, S, V (0, 1) format. + * + * @param signature signature base64 string + * @return secp256k1 signature (v = 0,1) + */ + public static RsvSignature SigBase64Deserialization(String signature) { + byte[] sigBytes = base64Decode(signature.getBytes(StandardCharsets.UTF_8)); + if (SERIALIZED_SIGNATUREDATA_LENGTH != sigBytes.length) { + throw new WeIdBaseException("signature data illegal"); + } + byte[] r = new byte[32]; + byte[] s = new byte[32]; + System.arraycopy(sigBytes, 0, r, 0, 32); + System.arraycopy(sigBytes, 32, s, 0, 32); + RsvSignature rsvSignature = new RsvSignature(); + rsvSignature.setR(new Bytes32(r)); + rsvSignature.setS(new Bytes32(s)); + rsvSignature.setV(new Uint8(sigBytes[64])); + return rsvSignature; + } + + /** + * Verify secp256k1 signature. + * + * @param rawData original raw data + * @param signatureBase64 signature string + * @param publicKey in BigInteger format + * @return return boolean result, true is success and false is fail + */ + public static boolean verifySignature( + String rawData, + String signatureBase64, + BigInteger publicKey + ) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.verifySignature(rawData, signatureBase64, publicKey); + } else { + // default database + try { + if (rawData == null) { + return false; + } + RsvSignature rsvSignature = SigBase64Deserialization(signatureBase64); + String messageHash = hash(rawData); + return verifySignature(publicKey.toString(16), messageHash, rsvSignature); + } catch (Exception e) { + logger.error("Error occurred during secp256k1 sig verification: {}", e); + return false; + } + } + } + + /** + * Verify secp256k1 signature. + * + * @param hexPublicKey publicKey in hex string + * @param messageHash hash of original raw data + * @param rsvSignature signature value + * @return return boolean result, true is success and false is fail + */ + public static boolean verifySignature( + String hexPublicKey, + String messageHash, + RsvSignature rsvSignature + ) { + if(cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE) { + ECDSASignatureResult signatureResult = new ECDSASignatureResult( + rsvSignature.getV().getValue().byteValueExact(), + rsvSignature.getR().getValue(), + rsvSignature.getS().getValue()); + return cryptoSuite.verify(hexPublicKey, messageHash, signatureResult.convertToString()); + } else { +// byte[] sigBytes = new byte[64]; +// System.arraycopy(rsvSignature.getR(), 0, sigBytes, 0, 32); +// System.arraycopy(rsvSignature.getS(), 0, sigBytes, 32, 32); + SM2SignatureResult signatureResult = new SM2SignatureResult( + Numeric.hexStringToByteArray(hexPublicKey), //todo pub of sm2 sig + rsvSignature.getR().getValue(), + rsvSignature.getS().getValue()); + return cryptoSuite.verify(hexPublicKey, messageHash, signatureResult.convertToString()); + } + } + + /** + * encrypt the data. todo + * + * @param data the data to encrypt + * @param publicKey public key + * @return decrypt data + * @throws Exception encrypt exception + */ + public static byte[] encrypt(String data, String publicKey) throws Exception { + /* + cryptoSuite.ECCEncrypt encrypt = new ECCEncrypt(new BigInteger(publicKey)); + return encrypt.encrypt(data.getBytes()); + + */ + return data.getBytes(); + } + + + /** + * decrypt the data. todo + * + * @param data the data to decrypt + * @param privateKey private key + * @return original data + * @throws Exception decrypt exception + */ + public static byte[] decrypt(byte[] data, String privateKey) throws Exception { + + /*ECCDecrypt decrypt = new ECCDecrypt(new BigInteger(privateKey)); + return decrypt.decrypt(data);*/ + return data; + } + + + /** + * hexString of pub or private key convert to decimal string + * @param keyInHex private key or pub key in hex string + * @return decimal string + */ + public static String hexStr2DecStr(String keyInHex) { + byte[] keyBytes = Numeric.hexStringToByteArray(keyInHex); + return new BigInteger(1, keyBytes).toString(10); + } + + /** + * generate private key + * @return decimal private key + */ + public static String generatePrivateKey() { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.generatePrivateKey(); + } else { + // default database + return hexStr2DecStr(cryptoSuite.getKeyPairFactory().generateKeyPair().getHexPrivateKey()); + } + } + + /** + * Obtain the PublicKey from given PrivateKey. + * + * @param privateKey the private key + * @return publicKey + */ + public static BigInteger publicKeyFromPrivate(BigInteger privateKey) { + return new BigInteger(publicKeyStrFromPrivate(privateKey)); + } + + /** + * Obtain the PublicKey from given PrivateKey. + * + * @param privateKey the private key + * @return publicKey decimal + */ + public static String publicKeyStrFromPrivate(BigInteger privateKey) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.publicKeyStrFromPrivate(privateKey); + } else { + // default database + return hexStr2DecStr(cryptoSuite.getKeyPairFactory().createKeyPair(privateKey).getHexPublicKey()); + } + } + + /** + * Obtain the PublicKey from given PrivateKey. + * + * @param privateKey the private key + * @return publicKey + */ + public static String addressFromPrivate(BigInteger privateKey) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.addressFromPrivate(privateKey); + } else { + // default database + return cryptoSuite.getKeyPairFactory().createKeyPair(privateKey).getAddress(); + } + } + + /** + * Obtain the PublicKey from given PrivateKey. + * + * @param publicKey the public key + * @return publicKey + */ + public static String addressFromPublic(BigInteger publicKey) { + if (deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.addressFromPublic(publicKey); + } else { + // default database + return Numeric.toHexString(cryptoSuite.getKeyPairFactory().getAddress(publicKey)); + } + } + + + /** + * The Base64 encode/decode class. + * + * @param base64Bytes the base 64 bytes + * @return the byte[] + */ + public static byte[] base64Decode(byte[] base64Bytes) { + return Base64.decode(base64Bytes); + } + + /** + * Base 64 encode. + * + * @param nonBase64Bytes the non base 64 bytes + * @return the byte[] + */ + public static byte[] base64Encode(byte[] nonBase64Bytes) { + return Base64.encode(nonBase64Bytes); + } + + /** + * Checks if is valid base 64 string. + * + * @param string the string + * @return true, if is valid base 64 string + */ + public static boolean isValidBase64String(String string) { + return org.apache.commons.codec.binary.Base64.isBase64(string); + } + + /** + * Verify a signature (base64). + * + * @param rawData the rawData to be verified + * @param signature the Signature Data in Base64 style + * @param weIdDocument the WeIdDocument to be extracted + * @param methodId the WeID public key ID + * @return true if yes, false otherwise with exact error codes + */ + public static ErrorCode verifySignatureFromWeId( + String rawData, + String signature, + WeIdDocument weIdDocument, + String methodId) { + + String foundMatchingMethodId = StringUtils.EMPTY; + try { + boolean result = false; + for (AuthenticationProperty authenticationProperty : weIdDocument.getAuthentication()) { + if (StringUtils.isNotEmpty(authenticationProperty.getPublicKey())) { + boolean currentResult = verifySignature( + rawData, signature, new BigInteger(authenticationProperty.getPublicKey())); + result = currentResult || result; + if (currentResult) { + foundMatchingMethodId = authenticationProperty.getId(); + break; + } + } + } + if (!result) { + return ErrorCode.CREDENTIAL_VERIFY_FAIL; + } + } catch (Exception e) { + logger.error("some exceptions occurred in signature verification", e); + return ErrorCode.CREDENTIAL_EXCEPTION_VERIFYSIGNATURE; + } + if (!StringUtils.isEmpty(methodId) + && !foundMatchingMethodId.equalsIgnoreCase(methodId)) { + return ErrorCode.CREDENTIAL_VERIFY_SUCCEEDED_WITH_WRONG_PUBLIC_KEY_ID; + } + return ErrorCode.SUCCESS; + } + + + /** + * Convert an off-chain Base64 signature String to signatureData format. + * + * @param base64Signature the signature string in Base64 + * @return signatureData structure + */ + //public static SignatureData convertBase64StringToSignatureData(String base64Signature) { + /*public static ECDSASignatureResult convertBase64StringToSignatureData(String base64Signature) { + return simpleSignatureDeserialization( + base64Decode(base64Signature.getBytes(StandardCharsets.UTF_8)) + ); + }*/ + + /** + * Get the UUID and remove the '-'. + * + * @return return the UUID of the length is 32 + */ + public static String getUuId32() { + return UUID.randomUUID().toString().replaceAll(SEPARATOR_CHAR, StringUtils.EMPTY); + } + + /** + * convert byte array to string. + * + * @param bytearray byte[] + * @return String + */ + public static String byteToString(byte[] bytearray) { + String result = ""; + char temp; + + int length = bytearray.length; + for (int i = 0; i < length; i++) { + temp = (char) bytearray[i]; + result += temp; + } + return result; + } + + /** + * string to byte. + * + * @param value stringData + * @return byte[] + */ + public static byte[] stringToByteArray(String value) { + if (StringUtils.isBlank(value)) { + return new byte[1]; + } + return value.getBytes(StandardCharsets.UTF_8); + } + + private static synchronized List splitBytes(byte[] bytes, int size) { + List byteList = new ArrayList<>(); + double splitLength = + Double.parseDouble(WeIdConstant.MAX_AUTHORITY_ISSUER_NAME_LENGTH + ""); + int arrayLength = (int) Math.ceil(bytes.length / splitLength); + byte[] result = new byte[arrayLength]; + + int from = 0; + int to = 0; + + for (int i = 0; i < arrayLength; i++) { + from = (int) (i * splitLength); + to = (int) (from + splitLength); + + if (to > bytes.length) { + to = bytes.length; + } + + result = Arrays.copyOfRange(bytes, from, to); + if (result.length < size) { + byte[] newBytes = new byte[32]; + System.arraycopy(result, 0, newBytes, 0, result.length); + byteList.add(newBytes); + } else { + byteList.add(result); + } + } + return byteList; + } + + + /** + // * Generate Default CPT Json Schema based on a given CPT ID. + * get Default CPT Json Schema from default constant class by given CPT ID + * @param cptId the CPT ID + * @return CPT Schema in Json String + */ + public static String generateDefaultCptJsonSchema(Integer cptId) { + try { + return RawCptSchema.getCptSchema(cptId); + } catch (Exception e) { + return StringUtils.EMPTY; + } + } + + + /** + * Generate unformatted CPT which allows any format, to support external invocation. + * + * @return CPT Schema in Json String + */ + public static String generateUnformattedCptJsonSchema() { + List> anyStringList = new ArrayList<>(); + Map stringMap = new HashMap<>(); + stringMap.put("type", "string"); + anyStringList.add(stringMap); + Map nullMap = new HashMap<>(); + nullMap.put("type", "null"); + anyStringList.add(nullMap); + Map anyMap = new LinkedHashMap<>(); + anyMap.put("anyOf", anyStringList); + Map patternMap = new LinkedHashMap<>(); + patternMap.put("^.*$", anyMap); + Map cptSchemaMap = new LinkedHashMap<>(); + cptSchemaMap.put(JsonSchemaConstant.SCHEMA_KEY, JsonSchemaConstant.SCHEMA_VALUE); + cptSchemaMap.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_OBJECT); + cptSchemaMap.put("title", "Unformatted CPT"); + cptSchemaMap.put("description", "Universal unformatted CPT template"); + cptSchemaMap.put("patternProperties", patternMap); + return DataToolUtils.objToJsonStrWithNoPretty(cptSchemaMap); + } + + /** + * Check if the byte array is empty. + * + * @param byteArray the byte[] + * @return true if empty, false otherwise + */ + public static boolean isByteArrayEmpty(byte[] byteArray) { + for (int index = 0; index < byteArray.length; index++) { + if (byteArray[index] != 0) { + return false; + } + } + return true; + } + + /** + * Get the current timestamp as the param "created". May be called elsewhere. + * + * @param length length + * @return the StaticArray + */ + public static List getParamCreatedList(int length) { + long created = DateUtils.getNoMillisecondTimeStamp(); + List createdList = new ArrayList<>(); + createdList.add(BigInteger.ZERO); + createdList.add(BigInteger.valueOf(created)); + return createdList; + } + + /** + * convert timestamp to UTC of json string. + * + * @param jsonString json string + * @return timestampToUtcString + */ + public static String convertTimestampToUtc(String jsonString) { + String timestampToUtcString; + try { + timestampToUtcString = dealNodeOfConvertUtcAndLong( + loadJsonObject(jsonString), + CONVERT_UTC_LONG_KEYLIST, + TO_JSON + ).toString(); + } catch (IOException e) { + logger.error("replaceJsonObj exception.", e); + throw new DataTypeCastException(e); + } + return timestampToUtcString; + } + + /** + * convert UTC Date to timestamp of Json string. + * + * @param jsonString presentationJson + * @return presentationJson after convert + */ + public static String convertUtcToTimestamp(String jsonString) { + String utcToTimestampString; + try { + utcToTimestampString = dealNodeOfConvertUtcAndLong( + loadJsonObject(jsonString), + CONVERT_UTC_LONG_KEYLIST, + FROM_JSON + ).toString(); + } catch (IOException e) { + logger.error("replaceJsonObj exception.", e); + throw new DataTypeCastException(e); + } + return utcToTimestampString; + } + + private static JsonNode dealNodeOfConvertUtcAndLong( + JsonNode jsonObj, + List list, + String type) { + if (jsonObj.isObject()) { + return dealObjectOfConvertUtcAndLong((ObjectNode) jsonObj, list, type); + } else if (jsonObj.isArray()) { + return dealArrayOfConvertUtcAndLong((ArrayNode) jsonObj, list, type); + } else { + return jsonObj; + } + } + + private static JsonNode dealObjectOfConvertUtcAndLong( + ObjectNode jsonObj, + List list, + String type) { + ObjectNode resJson = OBJECT_MAPPER.createObjectNode(); + jsonObj.fields().forEachRemaining(entry -> { + String key = entry.getKey(); + JsonNode obj = entry.getValue(); + if (obj.isObject()) { + //JSONObject + if (key.equals(KEY_CLAIM)) { + resJson.set(key, obj); + } else { + resJson.set(key, dealObjectOfConvertUtcAndLong((ObjectNode) obj, list, type)); + } + } else if (obj.isArray()) { + //JSONArray + resJson.set(key, dealArrayOfConvertUtcAndLong((ArrayNode) obj, list, type)); + } else { + if (list.contains(key)) { + if (TO_JSON.equals(type)) { + if (isValidLongString(obj.asText())) { + resJson.put( + key, + DateUtils.convertNoMillisecondTimestampToUtc( + Long.parseLong(obj.asText()))); + } else { + resJson.set(key, obj); + } + } else { + if (DateUtils.isValidDateString(obj.asText())) { + resJson.put( + key, + DateUtils.convertUtcDateToNoMillisecondTime(obj.asText())); + } else { + resJson.set(key, obj); + } + } + } else { + resJson.set(key, obj); + } + } + }); + return resJson; + } + + private static JsonNode dealArrayOfConvertUtcAndLong( + ArrayNode jsonArr, + List list, + String type) { + ArrayNode resJson = OBJECT_MAPPER.createArrayNode(); + for (int i = 0; i < jsonArr.size(); i++) { + JsonNode jsonObj = jsonArr.get(i); + if (jsonObj.isObject()) { + resJson.add(dealObjectOfConvertUtcAndLong((ObjectNode) jsonObj, list, type)); + } else if (jsonObj.isArray()) { + resJson.add(dealArrayOfConvertUtcAndLong((ArrayNode) jsonObj, list, type)); + } else { + resJson.add(jsonObj); + } + } + return resJson; + } + + /** + * valid string is a long type. + * + * @param str string + * @return result + */ + public static boolean isValidLongString(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + + long result = 0; + int i = 0; + int len = str.length(); + long limit = -Long.MAX_VALUE; + long multmin; + int digit; + + char firstChar = str.charAt(0); + if (firstChar <= '0') { + return false; + } + multmin = limit / radix; + while (i < len) { + digit = Character.digit(str.charAt(i++), radix); + if (digit < 0) { + return false; + } + if (result < multmin) { + return false; + } + result *= radix; + if (result < limit + digit) { + return false; + } + result -= digit; + } + return true; + } + + /** + * valid the json string is converted by toJson(). + * + * @param json jsonString + * @return result + */ + public static boolean isValidFromToJson(String json) { + if (StringUtils.isBlank(json)) { + logger.error("input json param is null."); + return false; + } + JsonNode jsonObject = null; + try { + jsonObject = loadJsonObject(json); + } catch (IOException e) { + logger.error("convert jsonString to JSONObject failed." + e); + return false; + } + return jsonObject.has(KEY_FROM_TOJSON); + } + + /** + * add tag which the json string is converted by toJson(). + * + * @param json jsonString + * @return result + */ + public static String addTagFromToJson(String json) { + JsonNode jsonObject; + try { + jsonObject = loadJsonObject(json); + if (!jsonObject.has(KEY_FROM_TOJSON)) { + ((ObjectNode) jsonObject).put(KEY_FROM_TOJSON, TO_JSON); + } + } catch (IOException e) { + logger.error("addTagFromToJson fail." + e); + return json; + } + return jsonObject.toString(); + } + + /** + * remove tag which the json string is converted by toJson(). + * + * @param json jsonString + * @return result + */ + public static String removeTagFromToJson(String json) { + JsonNode jsonObject; + try { + jsonObject = loadJsonObject(json); + if (jsonObject.has(KEY_FROM_TOJSON)) { + ((ObjectNode) jsonObject).remove(KEY_FROM_TOJSON); + } + } catch (IOException e) { + logger.error("removeTag fail." + e); + return json; + } + return jsonObject.toString(); + } + + /** + * Check whether a URL String is a valid endpoint. + * + * @param url the endpoint url + * @return true if yes, false otherwise + */ + public static boolean isValidEndpointUrl(String url) { + if (StringUtils.isEmpty(url)) { + return false; + } + String hostname; + Integer port; + String endpointName; + try { + URI uri = new URI(url); + hostname = uri.getHost(); + port = uri.getPort(); + String path = uri.getPath(); + if (StringUtils.isEmpty(hostname) || StringUtils.isEmpty(path) || port < 0) { + logger.error("Service URL illegal: {}", url); + return false; + } + // Truncate the first slash + endpointName = path.substring(1); + if (StringUtils.isEmpty(endpointName)) { + return false; + } + } catch (Exception e) { + logger.error("Service URL format check failed: {}", url); + return false; + } + return true; + } + + /** + * check if the input string is Uft-8. + * + * @param string input + * @return true, otherwise false + */ + public static boolean isUtf8String(String string) { + try { + string.getBytes("UTF-8"); + return true; + } catch (UnsupportedEncodingException e) { + logger.error("Passed-in String is not a valid UTF-8 String."); + } + return false; + } + + /** + * Check whether the address is local address. + * + * @param host host string + * @return true if yes, false otherwise + */ + public static boolean isLocalAddress(String host) { + InetAddress addr; + try { + addr = InetAddress.getByName(host); + } catch (UnknownHostException e) { + logger.error("Unkown host: " + host); + return false; + } + // Check if the address is a valid special local or loop back + if (addr.isSiteLocalAddress() || addr.isAnyLocalAddress() || addr.isLoopbackAddress() + || addr.isLinkLocalAddress()) { + return true; + } + // Check if the address is defined on any interface + try { + return NetworkInterface.getByInetAddress(addr) != null; + } catch (SocketException e) { + return false; + } + } + + /** + * Convert a hash string (0x[64Bytes]) into a byte array with 32 bytes length by compressing + * each two nearby characters into one. + * + * @param hash hash String + * @return byte array + */ + public static byte[] convertHashStrIntoHashByte32Array(String hash) { + if (!isValidHash(hash)) { + return null; + } + byte[] originHashByte = hash.getBytes(StandardCharsets.UTF_8); + byte[] result = new byte[WeIdConstant.BYTES32_FIXED_LENGTH]; + for (int i = 0; i < WeIdConstant.BYTES32_FIXED_LENGTH; i++) { + String hex = new String( + new byte[]{originHashByte[2 + i * 2], originHashByte[3 + i * 2]}); + int val = Integer.parseInt(hex, 16); + result[i] = (byte) val; + } + return result; + } + + /** + * Convert a byte array with 32 bytes into a hash String by stretching the two halfs of a hex + * byte into two separate hex string. Padding with zeros must be kept in mind. + * + * @param hash hash byte array + * @return hash String + */ + public static String convertHashByte32ArrayIntoHashStr(byte[] hash) { + StringBuilder convertedBackStr = new StringBuilder().append(WeIdConstant.HEX_PREFIX); + for (int i = 0; i < WeIdConstant.BYTES32_FIXED_LENGTH; i++) { + String hex = Integer + .toHexString(((int) hash[i]) >= 0 ? ((int) hash[i]) : ((int) hash[i]) + 256); + if (hex.length() == 1) { + hex = "0" + hex; + } + convertedBackStr.append(hex); + } + return convertedBackStr.toString(); + } + + /** + * An intermediate fix to convert Bytes32 Object List from web3sdk 2.x into a real String list. + * + * @param byteList Bytes32 Object list + * @return hash String list + */ + public static List convertBytes32ObjectListToStringHashList( + List byteList) { + List strList = new ArrayList<>(); + for (int i = 0; i < byteList.size(); i++) { + strList.add(DataToolUtils.convertHashByte32ArrayIntoHashStr( + //((org.fisco.bcos.web3j.abi.datatypes.generated.Bytes32) (byteList.toArray()[i])) + ((Bytes32) (byteList.toArray()[i])) + .getValue())); + } + return strList; + } + + /** + * Strictly check two lists' elements existence whether items in src exists in dst list or not. + * + * @param src source list + * @param dst dest list + * @return boolean list, each true / false indicating existing or not. + */ + public static List strictCheckExistence(List src, List dst) { + List result = new ArrayList<>(); + int index = 0; + for (int i = 0; i < src.size(); i++) { + if (src.get(i).equalsIgnoreCase(dst.get(index))) { + result.add(true); + index++; + } else { + result.add(false); + } + } + return result; + } +} + diff --git a/src/main/java/com/webank/weid/util/DataTypetUtils.java b/src/main/java/com/webank/weid/util/DataTypetUtils.java deleted file mode 100644 index 03798630..00000000 --- a/src/main/java/com/webank/weid/util/DataTypetUtils.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.util; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; - -/** - * Data type conversion utilities between solidity data type and java data type. - * - * @author lingfenghe - */ -public final class DataTypetUtils { - - /** - * Bytes array to bytes 32. - * - * @param byteValue the byte value - * @return the bytes 32 - */ - public static Bytes32 bytesArrayToBytes32(byte[] byteValue) { - byte[] byteValueLen32 = new byte[32]; - System.arraycopy(byteValue, 0, byteValueLen32, 0, byteValue.length); - return new Bytes32(byteValueLen32); - } - - /** - * String to bytes 32. - * - * @param string the string - * @return the bytes 32 - */ - public static Bytes32 stringToBytes32(String string) { - byte[] byteValue = string.getBytes(); - byte[] byteValueLen32 = new byte[32]; - System.arraycopy(byteValue, 0, byteValueLen32, 0, byteValue.length); - return new Bytes32(byteValueLen32); - } - - /** - * Bytes 32 to bytes array. - * - * @param bytes32 the bytes 32 - * @return the byte[] - */ - public static byte[] bytes32ToBytesArray(Bytes32 bytes32) { - byte[] bytesArray = new byte[32]; - byte[] bytes32Value = bytes32.getValue(); - System.arraycopy(bytes32Value, 0, bytesArray, 0, 32); - return bytesArray; - } - - /** - * Convert a Byte32 data to Java String. IMPORTANT NOTE: Byte to String is not 1:1 mapped. So - - * Know your data BEFORE do the actual transform! For example, Deximal Bytes, or ASCII Bytes are - * OK to be in Java String, but Encrypted Data, or raw Signature, are NOT OK. - * - * @param bytes32 the bytes 32 - * @return String - */ - public static String bytes32ToString(Bytes32 bytes32) { - byte[] strs = bytes32.getValue(); - String str = new String(strs); - return str.trim(); - } - - /** - * Bytes 32 to string without trim. - * - * @param bytes32 the bytes 32 - * @return the string - */ - public static String bytes32ToStringWithoutTrim(Bytes32 bytes32) { - byte[] strs = bytes32.getValue(); - String str = new String(strs); - return str; - } - - /** - * Int to uint 256. - * - * @param value the value - * @return the uint 256 - */ - public static Uint256 intToUint256(int value) { - return new Uint256(new BigInteger(String.valueOf(value))); - } - - /** - * Uint 256 to int. - * - * @param value the value - * @return the int - */ - public static int uint256ToInt(Uint256 value) { - return value.getValue().intValue(); - } - - /** - * String to dynamic bytes. - * - * @param input the input - * @return the dynamic bytes - */ - public static DynamicBytes stringToDynamicBytes(String input) { - return new DynamicBytes(input.getBytes()); - } - - /** - * Dynamic bytes to string. - * - * @param input the input - * @return the string - */ - public static String dynamicBytesToString(DynamicBytes input) { - return new String(input.getValue()); - } - - /** - * Int to int 256. - * - * @param value the value - * @return the int 256 - */ - public static Int256 intToInt256(int value) { - return new Int256(value); - } - - /** - * Int 256 to int. - * - * @param value the value - * @return the int - */ - public static int int256ToInt(Int256 value) { - return value.getValue().intValue(); - } - - /** - * Int to unt 8. - * - * @param value the value - * @return the uint 8 - */ - public static Uint8 intToUnt8(int value) { - return new Uint8(value); - } - - /** - * Uint 8 to int. - * - * @param value the value - * @return the int - */ - public static int uint8ToInt(Uint8 value) { - return value.getValue().intValue(); - } - - /** - * Long to int 256. - * - * @param value the value - * @return the int 256 - */ - public static Int256 longToInt256(long value) { - return new Int256(value); - } - - /** - * Int 256 to long. - * - * @param value the value - * @return the long - */ - public static long int256ToLong(Int256 value) { - return value.getValue().longValue(); - } - - /** - * Long array to int 256 static array. - * - * @param longArray the long array - * @return the static array - */ - public static StaticArray longArrayToInt256StaticArray(long[] longArray) { - List int256List = new ArrayList(); - for (int i = 0; i < longArray.length; i++) { - int256List.add(longToInt256(longArray[i])); - } - StaticArray in256StaticArray = new StaticArray(int256List); - return in256StaticArray; - } - - /** - * String array to bytes 32 static array. - * - * @param stringArray the string array - * @return the static array - */ - public static StaticArray stringArrayToBytes32StaticArray(String[] stringArray) { - List bytes32List = new ArrayList(); - for (int i = 0; i < stringArray.length; i++) { - if (StringUtils.isNotEmpty(stringArray[i])) { - bytes32List.add(stringToBytes32(stringArray[i])); - } else { - bytes32List.add(stringToBytes32(StringUtils.EMPTY)); - } - } - StaticArray bytes32StaticArray = new StaticArray(bytes32List); - return bytes32StaticArray; - } - - /** - * Bytes 32 dynamic array to string array without trim. - * - * @param bytes32DynamicArray the bytes 32 dynamic array - * @return the string[] - */ - public static String[] bytes32DynamicArrayToStringArrayWithoutTrim( - DynamicArray bytes32DynamicArray) { - List bytes32List = bytes32DynamicArray.getValue(); - String[] stringArray = new String[bytes32List.size()]; - for (int i = 0; i < bytes32List.size(); i++) { - stringArray[i] = bytes32ToStringWithoutTrim(bytes32List.get(i)); - } - return stringArray; - } - - /** - * Int 256 dynamic array to long array. - * - * @param int256DynamicArray the int 256 dynamic array - * @return the long[] - */ - public static long[] int256DynamicArrayToLongArray(DynamicArray int256DynamicArray) { - List int256list = int256DynamicArray.getValue(); - long[] longArray = new long[int256list.size()]; - for (int i = 0; i < int256list.size(); i++) { - longArray[i] = int256ToLong(int256list.get(i)); - } - return longArray; - } -} diff --git a/src/main/java/com/webank/weid/util/DateUtils.java b/src/main/java/com/webank/weid/util/DateUtils.java index cd15186a..bec3c100 100644 --- a/src/main/java/com/webank/weid/util/DateUtils.java +++ b/src/main/java/com/webank/weid/util/DateUtils.java @@ -1,31 +1,21 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.TimeZone; -import org.bcos.web3j.abi.datatypes.generated.Int256; +import org.fisco.bcos.sdk.abi.datatypes.generated.Int256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Date formatter utilities. @@ -34,13 +24,21 @@ */ public class DateUtils { + private static final Logger logger = LoggerFactory.getLogger(DateUtils.class); + + private static String TIME_ZONE = "Asia/Shanghai"; + + private static String STRING_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + private static String UTC_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + /** * Get the ISO8601 timestamp. * * @param date the date * @return the ISO 8601 timestamp */ - public static String getISO8601Timestamp(Date date) { + public static String getTimestamp(Date date) { return getDefaultDateFormat().format(date); } @@ -50,7 +48,7 @@ public static String getISO8601Timestamp(Date date) { * @param date the date * @return the ISO 8601 timestamp */ - public static String getISO8601Timestamp(long date) { + public static String getTimestamp(long date) { return getDefaultDateFormat().format(date); } @@ -66,6 +64,16 @@ private static DateFormat getDefaultDateFormat() { return df; } + /** + * Gets the default date format. + * + * @return the default date format + */ + private static DateTimeFormatter getDefaultDateTimeFormatter() { + DateTimeFormatter ftf = DateTimeFormatter.ofPattern(UTC_DATE_FORMAT); + return ftf.withZone(ZoneId.of(TIME_ZONE)); + } + /** * Convert a String to Date based on a specific DateFormat. * @@ -91,48 +99,88 @@ public static Date convertLongStringToDate(String dateString) throws ParseExcept /** * Conver date to time stamp. * - * @param time the time - * @return the long + * @param time the time in Date + * @return the long timestamp * @throws ParseException the parse exception */ public static long converDateToTimeStamp(String time) throws ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(STRING_DATE_FORMAT); Date date = simpleDateFormat.parse(time); long ts = date.getTime(); return ts; } + /** + * Conver utc date to time stamp. + * + * @param time the time in UTC + * @return the long timestamp + * @throws ParseException the parse exception + */ + public static Long convertUtcDateToTimeStamp(String time) throws ParseException { + DateFormat simpleDateFormat = getDefaultDateFormat(); + Date date = simpleDateFormat.parse(time); + return date.getTime(); + } + + /** + * Conver utc date to without millisecond timestamp. + * + * @param time the time in UTC + * @return the long timestamp + */ + public static Long convertUtcDateToNoMillisecondTime(String time) { + DateTimeFormatter dtf = getDefaultDateTimeFormatter(); + LocalDateTime date = LocalDateTime.parse(time, dtf); + return date.toInstant(ZoneOffset.of("+8")).getEpochSecond(); + } + /** * Check the UTC format validity of a Date String. * * @param dateString the date string * @return true, if is valid UTC date string */ - public static boolean isValidUTCDateString(String dateString) { + public static boolean isValidDateString(String dateString) { try { DateFormat df = getDefaultDateFormat(); df.setLenient(false); df.parse(dateString); return true; - } catch (ParseException pEx) { + } catch (ParseException parseEx) { return false; } } /** - * Checks if is valid long date string. + * Check the timestamp date to UTC date string. * - * @param dateString the date string - * @return true, if is valid long date string + * @param date the timestamp string + * @return UTC formatted date string */ - public static boolean isValidLongDateString(String dateString) { - Long parsed; - try { - parsed = Long.parseLong(dateString); - } catch (Exception ex) { - return false; + public static String convertTimestampToUtc(Long date) { + DateFormat df = getDefaultDateFormat(); + df.setLenient(false); + return df.format(new Date(date)); + } + + /** + * Convert the timestamp without millisecond date to UTC date string. + * + * @param date the timestamp without millisecond string + * @return UTC formatted date string + */ + public static String convertNoMillisecondTimestampToUtc(Long date) { + if (String.valueOf(date) != null + && String.valueOf(date).length() == getNoMillisecondTimeStampString().length()) { + DateTimeFormatter dtf = getDefaultDateTimeFormatter(); + return dtf.format(LocalDateTime.ofInstant( + Instant.ofEpochSecond(date), + ZoneId.of(TIME_ZONE))); + } else { + logger.error("the timestamp is illegal."); + return null; } - return (parsed.intValue() >= 0); } /** @@ -144,6 +192,15 @@ public static Int256 getCurrentTimeStampInt256() { return new Int256(System.currentTimeMillis()); } + /** + * Get current no-ms timestamp in Int256 type. + * + * @return the current time stamp int 256 + */ + public static Int256 getNoMillisecondTimeStampInt256() { + return new Int256(DateUtils.getNoMillisecondTimeStamp()); + } + /** * Get current timestamp in String type. * @@ -152,4 +209,76 @@ public static Int256 getCurrentTimeStampInt256() { public static String getCurrentTimeStampString() { return String.valueOf(System.currentTimeMillis()); } + + /** + * Get current timestamp in long type. + * + * @return the current time stamp long + */ + public static Long getCurrentTimeStamp() { + return System.currentTimeMillis(); + } + + /** + * Get current timestamp without millisecond in long type. + * + * @return the current time stamp without millisecond long + */ + public static Long getNoMillisecondTimeStamp() { + return Instant.now().getEpochSecond(); + } + + /** + * Get current timestamp without millisecond in String type. + * + * @return the current time stamp without millisecond String + */ + public static String getNoMillisecondTimeStampString() { + return String.valueOf(Instant.now().getEpochSecond()); + } + + /** + * compare with the long date with CurrentTime. + * + * @param date long date + * @return boolean + */ + public static boolean isAfterCurrentTime(Long date) { + if (String.valueOf(date) != null + && String.valueOf(date).length() == getCurrentTimeStampString().length()) { + return date > getCurrentTimeStamp(); + } else if (String.valueOf(date) != null + && String.valueOf(date).length() == getNoMillisecondTimeStampString().length()) { + return date > getNoMillisecondTimeStamp(); + } else { + return false; + } + } + + /** + * convert timeStamp which contain millisecond to without millisecond timeStamp. + * + * @param date timeStamp + * @return the timeStamp without millisecond + */ + public static Long convertToNoMillisecondTimeStamp(Long date) { + if (String.valueOf(date) == null) { + logger.error("the timestamp is null."); + return null; + } + if (String.valueOf(date) != null + && String.valueOf(date).length() != getCurrentTimeStampString().length()) { + if (String.valueOf(date).length() == getNoMillisecondTimeStampString().length()) { + return date; + } + logger.error("the timestamp is illegal."); + return null; + } + DateTimeFormatter ftf = DateTimeFormatter.ofPattern(STRING_DATE_FORMAT); + String time = ftf.format( + LocalDateTime.ofInstant(Instant.ofEpochMilli(date), + ZoneId.of(TIME_ZONE))); + LocalDateTime parse = LocalDateTime.parse(time, ftf); + return LocalDateTime.from(parse).atZone(ZoneId.of(TIME_ZONE)).toInstant().getEpochSecond(); + } } diff --git a/src/main/java/com/webank/weid/util/HashUtils.java b/src/main/java/com/webank/weid/util/HashUtils.java deleted file mode 100644 index 7ce433df..00000000 --- a/src/main/java/com/webank/weid/util/HashUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.util; - -import org.bcos.web3j.crypto.Hash; - -/** - * The Hash related Utils class. Based on SHA3 algorithm. - * - *

Most implementations are re-factors or wrappers based on FISCO-BCOS web3j and Ethereumj. The - * future support of SM2/SM3 is under construction. - * - * @author chaoxinhu 2018.10 - */ -public class HashUtils { - - /** - * Keccak-256 hash function. - * - * @param hexInput hex encoded input data with optional 0x prefix - * @return hash value as hex encoded string - */ - public static String sha3(String hexInput) { - return Hash.sha3(hexInput); - } - - /** - * Keccak-256 hash function. - * - * @param input binary encoded input data - * @param offset (optional) offset of start of data - * @param length (optional) length of data - * @return hash value - */ - public static byte[] sha3(byte[] input, int offset, int length) { - return Hash.sha3(input, offset, length); - } - - /** - * Sha 3. - * - * @param input the input - * @return the byte[] - */ - public static byte[] sha3(byte[] input) { - return Hash.sha3(input, 0, input.length); - } -} diff --git a/src/main/java/com/webank/weid/util/HttpClient.java b/src/main/java/com/webank/weid/util/HttpClient.java new file mode 100644 index 00000000..00d150aa --- /dev/null +++ b/src/main/java/com/webank/weid/util/HttpClient.java @@ -0,0 +1,309 @@ + + +package com.webank.weid.util; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.TrustStrategy; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpClient { + + private static final Logger logger = LoggerFactory.getLogger(HttpClient.class); + + private static int httpRequestTimeOut = 15000; + + private static int httpMaxActive = 100; + + private static int httpValidateAfterInactivity = 1000; + + private static final String httpProxyHost = ""; + + private static final int httpProxyPort = 80; + + private static PoolingHttpClientConnectionManager connMgr; + private static RequestConfig requestConfig; + + static { + connMgr = new PoolingHttpClientConnectionManager(); + connMgr.setMaxTotal(httpMaxActive); + connMgr.setDefaultMaxPerRoute(httpMaxActive); + connMgr.setValidateAfterInactivity(httpValidateAfterInactivity); + + RequestConfig.Builder configBuilder = RequestConfig.custom(); + configBuilder.setConnectTimeout(httpRequestTimeOut); + configBuilder.setSocketTimeout(httpRequestTimeOut); + configBuilder.setConnectionRequestTimeout(httpRequestTimeOut); + requestConfig = configBuilder.build(); + } + + /** + * Create an ignoring Verify SSL Context. + * + * @return SSL Context object + * @throws Exception SSL suite error, or key mgmt error + */ + public static SSLContext createIgnoreVerifySsL() throws Exception { + + SSLContext sc = SSLContext.getInstance("TLSv1.2"); + + X509TrustManager trustManager = new X509TrustManager() { + @Override + public void checkClientTrusted( + X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + logger.debug("Skipping client-side check, params: ", paramString); + } + + @Override + public void checkServerTrusted( + X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + logger.debug("Skipping server-side check, params: ", paramString); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sc.init(null, new TrustManager[]{trustManager}, null); + return sc; + } + + /** + * On-demand, create an http client. + * + * @param proxyHost proxy host url + * @param proxyPort proxy port url + * @param proxyUsername proxy username + * @param proxyPassword proxy pwd + * @return http client + * @throws Exception any exception + */ + public static CloseableHttpClient createHttpClient(String proxyHost, int proxyPort, + String proxyUsername, String proxyPassword) throws Exception { + try { + HttpHost proxy = null; + if (StringUtils.isNotEmpty(proxyHost)) { + proxy = new HttpHost(proxyHost, proxyPort, "http"); + } + + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + if (StringUtils.isNotEmpty(proxyUsername) && StringUtils.isNotEmpty(proxyPassword)) { + credsProvider.setCredentials( + new AuthScope(proxyHost, proxyPort), + new UsernamePasswordCredentials(proxyUsername, proxyPassword)); + } + + SSLContext sslcontext = createIgnoreVerifySsL(); + + Registry socketFactoryRegistry = RegistryBuilder + .create() + .register("http", PlainConnectionSocketFactory.INSTANCE) + .register("https", new SSLConnectionSocketFactory(sslcontext)) + .build(); + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager( + socketFactoryRegistry); + HttpClients.custom().setConnectionManager(connManager); + + CloseableHttpClient client = null; + if (proxy == null) { + client = HttpClients.custom().setConnectionManager(connManager).build(); + } else { + client = HttpClients.custom().setConnectionManager(connManager) + .setProxy(proxy) + .setDefaultCredentialsProvider(credsProvider) + .build(); + } + + return client; + } catch (Exception e) { + logger.error("onWarning: create http client error" + e); + throw e; + } + } + + /** + * Send a GET request. + * + * @param url url + * @param isSsL whether to use SSL or not + * @return response in String + * @throws Exception any exception + */ + public static String doGet(String url, boolean isSsL) throws Exception { + logger.debug("doGet start. url:{}", url); + + CloseableHttpClient httpClient; + if (isSsL) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSsLConn()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = createHttpClient(httpProxyHost, httpProxyPort, "", ""); + } + HttpGet httpget = null; + CloseableHttpResponse httpResponse = null; + try { + httpget = new HttpGet(url); + + httpResponse = httpClient.execute(httpget); + logger.info("doGet response: {}", httpResponse); + int statusCode = httpResponse.getStatusLine().getStatusCode(); + + String result = ""; + if (statusCode >= 200 && statusCode < 300) { + HttpEntity entity = httpResponse.getEntity(); + if (entity != null) { + result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); + logger.debug("doGet result : " + result); + } + } else { + logger.warn("onWarning: doGet fail. statusCode:{}", statusCode); + } + EntityUtils.consume(httpResponse.getEntity()); + httpResponse.close(); + return result; + } catch (Exception e) { + logger.warn("onWarning: doGet fail. statusCode", e); + throw e; + } finally { + httpget.releaseConnection(); + if (httpResponse != null) { + try { + EntityUtils.consume(httpResponse.getEntity()); + httpResponse.close(); + } catch (IOException e) { + logger.error("onError: doGet consume fail : ", e); + throw e; + } + } + } + } + + /** + * Send a POST request (in raw K-V format). + * + * @param url url + * @param params object to send + * @param isSsL whether to use SSL or not + * @return response in String + * @throws Exception any exception + */ + public static String doPost(String url, Object params, boolean isSsL) throws Exception { + + String paramsString = DataToolUtils.serialize(params); + logger.debug("doPost start. url:{},params:{}", url, paramsString); + CloseableHttpClient httpClient; + if (isSsL) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSsLConn()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = createHttpClient(httpProxyHost, httpProxyPort, "", ""); + } + HttpPost httpPost = new HttpPost(url); + CloseableHttpResponse response = null; + + try { + httpPost.setConfig(requestConfig); + + httpPost.addHeader("Content-type", "application/json; charset=utf-8"); + httpPost.setHeader("Accept", "application/json"); + httpPost.setEntity( + new StringEntity(paramsString, Charset.forName("UTF-8")));//发送的参数 + + response = httpClient.execute(httpPost); + int statusCode = response.getStatusLine().getStatusCode(); + String result = null; + if (statusCode >= 200 && statusCode < 300) { + HttpEntity entity = response.getEntity(); + if (entity != null) { + result = EntityUtils.toString(response.getEntity(), "UTF-8"); + logger.debug("doPost result : " + result); + } + } + EntityUtils.consume(response.getEntity()); + response.close(); + return result; + } catch (Exception e) { + logger.error("onWarning: doPost fail", e); + throw e; + } finally { + httpPost.releaseConnection(); + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + response.close(); + } catch (IOException e) { + logger.error("onWarning: doPost consume fail : ", e); + throw e; + } + } + } + } + + private static SSLConnectionSocketFactory createSsLConn() throws Exception { + logger.debug("createSSLConn start..."); + + SSLConnectionSocketFactory sslsf = null; + try { + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, new TrustStrategy() { + public boolean isTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + return true; + } + }).build(); + + sslsf = new SSLConnectionSocketFactory(sslContext, new MyHostnameVerifier()); + logger.debug("createSSLConn end..."); + return sslsf; + } catch (GeneralSecurityException e) { + logger.error("Onwarning: createSSLConn fail:", e); + throw e; + } + } + + static class MyHostnameVerifier implements HostnameVerifier { + + @Override + public boolean verify(String s, SSLSession sslSession) { + return false; + } + } +} + diff --git a/src/main/java/com/webank/weid/util/JsonSchemaValidatorUtils.java b/src/main/java/com/webank/weid/util/JsonSchemaValidatorUtils.java deleted file mode 100644 index b3674baf..00000000 --- a/src/main/java/com/webank/weid/util/JsonSchemaValidatorUtils.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.util; - -import java.io.IOException; -import java.util.Iterator; - -import com.webank.weid.constant.WeIdConstant; - -import com.fasterxml.jackson.databind.JsonNode; -import com.github.fge.jackson.JsonLoader; -import com.github.fge.jsonschema.core.report.ProcessingMessage; -import com.github.fge.jsonschema.core.report.ProcessingReport; -import com.github.fge.jsonschema.main.JsonSchema; -import com.github.fge.jsonschema.main.JsonSchemaFactory; -import com.github.fge.jsonschema.processors.syntax.SyntaxValidator; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Json Schema Validator Util class. Based on com.github.fge.json-schema-validator versioned 2.2.6. - * - * @author chaoxinhu 2018.10 - */ -public class JsonSchemaValidatorUtils { - - private static final Logger logger = LoggerFactory.getLogger(JsonSchemaValidatorUtils.class); - - /** - * Load Json Object. Can be used to return both Json Data and Json Schema. - * - * @param jsonString the json string - * @return JsonNode - * @throws IOException Signals that an I/O exception has occurred. - */ - public static JsonNode loadJsonObject(String jsonString) throws IOException { - return JsonLoader.fromString(jsonString); - } - - /** - * Validate Json Data versus Json Schema. - * - * @param jsonData the json data - * @param jsonSchema the json schema - * @return true if yes, false otherwise - * @throws Exception the exception - */ - public static boolean validateJsonVersusSchema(String jsonData, String jsonSchema) - throws Exception { - JsonNode jsonDataNode = loadJsonObject(jsonData); - JsonNode jsonSchemaNode = loadJsonObject(jsonSchema); - JsonSchema schema = JsonSchemaFactory.byDefault().getJsonSchema(jsonSchemaNode); - - ProcessingReport report = schema.validate(jsonDataNode); - if (report.isSuccess()) { - logger.info(report.toString()); - return true; - } else { - Iterator it = report.iterator(); - String errorMsg = ""; - while (it.hasNext()) { - errorMsg += it.next().getMessage(); - } - logger.error("Json Schema Validator failed, error: " + errorMsg); - return false; - } - } - - /** - * Validate Json Schema format validity. - * - * @param jsonSchema the json schema - * @return true if yes, false otherwise - * @throws IOException Signals that an I/O exception has occurred. - */ - public static boolean isValidJsonSchema(String jsonSchema) throws IOException { - SyntaxValidator syntaxValidator = JsonSchemaFactory.byDefault().getSyntaxValidator(); - boolean result = syntaxValidator.schemaIsValid(loadJsonObject(jsonSchema)); - result = result && jsonSchema.contains("$schema"); - return result; - } - - /** - * validate Cpt Json Schema validity . - * - * @param cptJsonSchema the cpt json schema - * @return true, if is cpt json schema valid - * @throws IOException Signals that an I/O exception has occurred. - */ - public static boolean isCptJsonSchemaValid(String cptJsonSchema) throws IOException { - return StringUtils.isNotEmpty(cptJsonSchema) - && isValidJsonSchema(cptJsonSchema) - && cptJsonSchema.length() <= WeIdConstant.JSON_SCHEMA_MAX_LENGTH; - } -} diff --git a/src/main/java/com/webank/weid/util/JsonUtil.java b/src/main/java/com/webank/weid/util/JsonUtil.java new file mode 100644 index 00000000..b53ad4c3 --- /dev/null +++ b/src/main/java/com/webank/weid/util/JsonUtil.java @@ -0,0 +1,731 @@ + + +package com.webank.weid.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.POJONode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.sun.codemodel.ClassType; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JType; +import com.webank.wedpr.selectivedisclosure.PredicateType; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.exception.DataTypeCastException; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.CredentialPojo; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.IntStream; +import org.apache.commons.lang3.StringUtils; +import org.jsonschema2pojo.DefaultGenerationConfig; +import org.jsonschema2pojo.GenerationConfig; +import org.jsonschema2pojo.Jackson2Annotator; +import org.jsonschema2pojo.SchemaGenerator; +import org.jsonschema2pojo.SchemaMapper; +import org.jsonschema2pojo.SchemaStore; +import org.jsonschema2pojo.rules.RuleFactory; + +public class JsonUtil { + + private static final Pattern PATTERN = Pattern.compile("^\\[[0-9]{1,}\\]$"); + private static final Pattern PATTERN_ARRAY = Pattern.compile("(?<=\\[)([0-9]{1,})(?=\\])"); + private static final Pattern PATTERN_KEY = Pattern.compile(".*?(?=\\[[0-9]{1,}\\])"); + + private static final String KEY_CHAR = "."; + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + /** + * 根据Map类型的JsonSchema去抽取里面有效的Key的集合(平级). + * + * @param cptJsonSchema Map类型的JsonSchema + * @return 返回有效Key的集合 + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static List extractCptProperties(Map cptJsonSchema) + throws IOException { + + return extractCptProperties(DataToolUtils.serialize(cptJsonSchema)); + } + + /** + * 根据Json类型的JsonSchema去抽取里面有效的Key的集合(平级). + * + * @param cptJsonSchema Json类型的JsonSchema + * @return 返回有效Key的集合 + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static List extractCptProperties(String cptJsonSchema) throws IOException { + + JDefinedClass dc = getDefinedClass(cptJsonSchema); + Map resultMap = new LinkedHashMap(); + List resultList = new ArrayList(); + if (dc != null) { + dc.fields().entrySet().forEach(entry -> buildFromDefinedClass(resultMap, entry)); + //补充元数据 + Map result = replenishMeta(resultMap, new CredentialPojo()); + //將map拍平成一级json + String value = jsonToMonolayer(DataToolUtils.serialize(result), 10); + //提取平级Json中key的集合 + toJsonNode(value) + .fieldNames().forEachRemaining(resultList::add); + } + return resultList; + } + + /* + * 补充元数据. + */ + private static Map replenishMeta( + Map claim, + CredentialPojo credential) { + + Map result = new LinkedHashMap(); + if (credential != null) { + result.put(CredentialConstant.ID, credential.getId()); + result.put(CredentialConstant.CREDENTIAL_META_KEY_CPTID, credential.getCptId()); + result.put(CredentialConstant.CREDENTIAL_META_KEY_CONTEXT, credential.getContext()); + result.put(CredentialConstant.CREDENTIAL_META_KEY_ISSUER, credential.getIssuer()); + result + .put(CredentialConstant.CREDENTIAL_META_KEY_ISSUANCEDATE, + credential.getIssuanceDate()); + result.put(CredentialConstant.CREDENTIAL_META_KEY_EXPIRATIONDATE, + credential.getExpirationDate()); + result.put("claim", claim); + } + return result; + } + + /* + * 利用SchemaMapper去构建一个Class,即将Schema to pojo. + */ + private static JDefinedClass getDefinedClass(String cptJson) throws IOException { + + JCodeModel codeModel = new JCodeModel(); + GenerationConfig config = new DefaultGenerationConfig() { + @Override + public boolean isGenerateBuilders() { + return true; + } + }; + SchemaMapper schemaMapper = new SchemaMapper( + new RuleFactory(config, new Jackson2Annotator(config), new SchemaStore()), + new SchemaGenerator()); + schemaMapper.generate(codeModel, "Example", "cpt", cptJson); + return codeModel._getClass("cpt.Example"); + } + + /* + * 遍历JDefinedClass 里面的字段,该字段为有效的key. + */ + private static void buildFromDefinedClass( + Map resultMap, + Entry entry) { + + String key = entry.getKey(); + if (StringUtils.equals(key, JsonSchemaConstant.ADDITIONAL_PROPERTIES)) { + return; + } + resultMap.put(key, null); + JType jtype = entry.getValue().type(); + if (jtype instanceof JDefinedClass) { + buildByType(resultMap, key, jtype); + } else if (jtype instanceof JClass) { + JClass jclass = (JClass) jtype; + List list = jclass.getTypeParameters(); + if (list.size() > 0) { + buildByType(resultMap, key, list.get(0)); + fixArray(resultMap, key); + } + } + } + + /* + * 修复集合类型的长度,即默认指定长度. + */ + private static void fixArray(Map resultMap, String key) { + + ArrayList objList = new ArrayList<>(); + IntStream.range(0, maxArraySize()).forEach(i -> objList.add(resultMap.get(key))); + resultMap.put(key, objList); + } + + /* + * 通过Jtype获取,关联类的字段信息. + */ + private static void buildByType(Map resultMap, String key, JType jt) { + + if (jt instanceof JDefinedClass) { + JDefinedClass dc = (JDefinedClass) jt; + if (dc.getClassType() == ClassType.CLASS) { + Map map = new LinkedHashMap(); + dc.fields().entrySet().forEach(entry -> buildFromDefinedClass(map, entry)); + resultMap.put(key, map); + } + } + } + + /** + * 将credential转换成平级Json,重构了元数据key,并且如果数据中包含数据(集合), 如果超过指定长度则报错, 如果不足则补全至指定长度. + * + * @param credential 凭证 + * @return 返回处理后的平级Json + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static Map credentialToMonolayer(CredentialPojo credential) + throws IOException { + + Map result = replenishMeta(credential.getClaim(), credential); + ObjectNode objectNode = (ObjectNode) toJsonNode(DataToolUtils.serialize(result)); + return monolayerToMap(jsonToMonolayer(objectNode, maxArraySize(), 10)); + } + + private static int maxArraySize() { + + return Integer.parseInt(PropertyUtils.getProperty("zkp.cpt.array.length", "-1")); + } + + private static Map monolayerToMap(String json) throws IOException { + + JsonNode resultNode = toJsonNode(json); + Map resultMap = new HashMap(); + resultNode.fields() + .forEachRemaining(node -> resultMap.put(node.getKey(), node.getValue().asText())); + return resultMap; + } + + /** + * 将ClaimPolicy转换成平级Json,如果数据中包含数据(集合),如果超过指定长度则报错, 如果不足则补全至指定长度. + * + * @param claimPolicy 披露策略 + * @return 返回处理后的平级Json + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static String claimPolicyToMonolayer(ClaimPolicy claimPolicy) throws IOException { + + ObjectNode objectNode = (ObjectNode) toJsonNode( + claimPolicy.getFieldsToBeDisclosed()); + return jsonToMonolayer(objectNode, maxArraySize(), 0); + } + + /** + * 将多级Json转换成平级Json,无补全处理. + * + * @param json 多级Json字符串 + * @param radix 需要转换的进制 + * @return 返回平级Json + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static String jsonToMonolayer(String json, int radix) throws IOException { + + return jsonToMonolayer(toJsonNode(json), -1, radix); + } + + /** + * 将多级Json转换成平级Json. + * + * @param jsonNode 多级的JsonNode + * @param radix 需要转换的进制 + * @return 返回平级Json + */ + public static String jsonToMonolayer(JsonNode jsonNode, int radix) { + + return jsonToMonolayer(jsonNode, -1, radix); + } + + /* + * 多级转平级处理. + */ + private static String jsonToMonolayer(JsonNode jsonNode, int maxSize, int radix) { + + JsonNode resultJson = MAPPER.createObjectNode(); + jsonNode.fields().forEachRemaining(node -> + parseJsonToNode(resultJson, node, new ArrayList(), maxSize, radix)); + return resultJson.toString(); + } + + /* + * 遍历处理原JsonNode里面的数据,放入新JsonNode(Object)中. + */ + private static void parseJsonToNode( + + JsonNode resultJson, + Entry entry, + List names, + int maxSize, + int radix) { + + names.add(entry.getKey()); + processNode(resultJson, entry.getValue(), names, maxSize, radix); + } + + /* + * 遍历处理原JsonNode里面的数据,放入新JsonNode(Array)中. + */ + private static void parseJsonToArray( + + JsonNode resultJson, + JsonNode value, + List names, + int index, + int maxSize, + int radix) { + + names.add("[" + index + "]"); + processNode(resultJson, value, names, maxSize, radix); + } + + /* + * 原节点处理,区分是Object、Array或是具体数据. + */ + private static void processNode( + JsonNode resultJson, + JsonNode value, + List names, + int maxSize, + int radix) { + + if (value.isObject() && !isBottom(value)) { + + value.fields().forEachRemaining(node -> + parseJsonToNode(resultJson, node, new ArrayList(names), maxSize, radix)); + } else if (value.isArray() && !isSampleArray(value)) { + fixLengthForArrayNode(value, maxSize); + value.forEach(consumerWithIndex((node, index) -> + parseJsonToArray( + resultJson, + node, + new ArrayList(names), + index, + maxSize, + radix))); + } else { + buildValue( + (ObjectNode) resultJson, + buildKey(names), + value, + ConvertType.STRING_TO_DECIMAL, + radix); + } + } + + /* + * 集合数据长度修正. + */ + private static void fixLengthForArrayNode(JsonNode value, int maxSize) { + + //判断数组长度 + if (maxSize != -1 && value.size() > maxSize) { //如果长度超过限制长度,则抛异常 + throw new RuntimeException("the array size:" + value.size() + ", maxSize:" + maxSize); + } + ArrayNode array = (ArrayNode) value; + if (maxSize - value.size() > 0) { + JsonNode jsonNode = cloneNodewithNullNode(array.get(array.size() - 1)); + IntStream.range(0, maxSize - value.size()).forEach(i -> array.add(jsonNode)); + } + } + + /* + * 节点克隆操作. + */ + private static JsonNode cloneNodewithNullNode(JsonNode node) { + + if (node.isObject()) { + ObjectNode objectNode = MAPPER.createObjectNode(); + node.fields().forEachRemaining(entry -> + cloneObjectNode(objectNode, entry.getKey(), entry.getValue())); + return objectNode; + } else if (node.isArray()) { + ArrayNode arrayNode = MAPPER.createArrayNode(); + node.forEach(childNode -> arrayNode.add(cloneNodewithNullNode(childNode))); + return arrayNode; + } else { + return TextNode.valueOf("null"); + } + } + + /* + * 节点克隆操作. + */ + private static void cloneObjectNode(ObjectNode resultNode, String key, JsonNode value) { + + if (value.isObject()) { + resultNode.set(key, cloneNodewithNullNode(value)); + } else if (value.isArray()) { + ArrayNode array = resultNode.putArray(key); + value.forEach(childNode -> array.add(cloneNodewithNullNode(childNode))); + } else { + if (value.isBigDecimal()) { + resultNode.set(key, IntNode.valueOf(0)); + } else { + resultNode.set(key, TextNode.valueOf("null")); + } + } + } + + private static boolean isBottom(JsonNode value) { + + if (value.isValueNode()) { + return true; + } else if (!value.isObject()) { + return false; + } + for (PredicateType type : PredicateType.values()) { + if (value.has(type.toString())) { + return true; + } + } + return false; + } + + /* + * 判断是否为纯基本数据集合. + */ + private static boolean isSampleArray(JsonNode value) { + + //说明不是数组 + if (!value.isArray()) { + return false; + } + return isSampleArray((ArrayNode) value); + } + + /* + * 判断是否为纯基本数据集合. + */ + private static boolean isSampleArray(ArrayNode array) { + + for (JsonNode jsonNode : array) { + if (jsonNode.isObject()) { + return false; + } else if (jsonNode.isArray()) { + if (!isSampleArray((ArrayNode) jsonNode)) { + return false; + } + } + } + return true; + } + + /* + * 将解析出来的多级key转换成平级key. + */ + private static String buildKey(List names) { + + StringBuilder buildKey = new StringBuilder(); + for (int i = 0; i < names.size(); i++) { + buildKey.append(names.get(i)); + if (i < names.size() - 1) { + String keyString = names.get(i + 1); + if (PATTERN.matcher(keyString).matches()) { + continue; + } + buildKey.append(KEY_CHAR); + } + } + return buildKey.toString(); + } + + /* + * 将节点数据放入新节点中. + */ + private static void buildValue( + ObjectNode resultJson, + String key, + JsonNode value, + ConvertType type, + int radix) { + + if (value.isObject()) { + resultJson.putPOJO(key, value); + } else if (value.isInt()) { + resultJson.put(key, value.asInt()); + } else if (value.isLong()) { + resultJson.put(key, value.asLong()); + } else if (value.isBigDecimal()) { + resultJson.put(key, value.asDouble()); + } else { + buildOtherValue(resultJson, key, value, type, radix); + } + } + + /* + * 将节点数据放入新节点中,处理非数字类型数据. + */ + private static void buildOtherValue( + ObjectNode resultJson, + String key, + JsonNode value, + ConvertType type, + int radix) { + + String strValue = null; + if (!value.isNull()) { + String nodeValue = value.asText(); + if (type == ConvertType.DECIMAL_TO_STRING) { + strValue = decimalToString(nodeValue, radix); + JsonNode vauleNode = toJsonNode(strValue); + if (vauleNode != null && vauleNode.isArray()) { + resultJson.putPOJO(key, vauleNode); + return; + } + } else if (type == ConvertType.STRING_TO_DECIMAL) { + if (value.isArray()) { + nodeValue = value.toString(); + } + strValue = toDecimal(nodeValue, radix); + } + } + resultJson.put(key, strValue); + } + + /* + * 将字符串转换成JsonNode. + */ + private static JsonNode toJsonNode(String jsonString) { + try { + return MAPPER.readTree(jsonString); + } catch (JsonProcessingException e) { + throw new DataTypeCastException(e); + } + } + + /* + * 字符串转10进制数字字符串. + */ + private static String toDecimal(String value, int radix) { + + if (StringUtils.isBlank(value)) { + return StringUtils.EMPTY; + } + if (radix == 0) { + return value; + } + return new BigInteger(1, value.getBytes(StandardCharsets.UTF_8)).toString(radix); + } + + /* + * 将10进制数字字符串还原成原字符串. + */ + private static String decimalToString(String value, int radix) { + + if (StringUtils.isBlank(value)) { + return StringUtils.EMPTY; + } + if (radix == 0) { + return value; + } + return new String(new BigInteger(value, radix).toByteArray(), StandardCharsets.UTF_8); + } + + /** + * 带循环下标的循环. + * + * @param 循环出来的泛型对象 + * @param consumer 用户包装循环的Consumer + * @return 包装了循环出来的对象和下标的对象 + */ + public static Consumer consumerWithIndex(BiConsumer consumer) { + + class Index { + + int index; + } + + Index indexObj = new Index(); + return t -> { + int index = indexObj.index++; + consumer.accept(t, index); + }; + } + + /** + * 将平级Json转换成多级Json. + * + * @param json 平级Json字符串 + * @param radix 需要转换的进制 + * @return 返回一个多级的Json字符串 + * @throws IOException 可能出现的异常,如JSON序列化异常 + */ + public static String monolayerToJson(String json, int radix) throws IOException { + + return monolayerToJson(toJsonNode(json), radix); + } + + /** + * 将平级Json转换成多级Json. + * + * @param jsonNode 平级JsonNode对象 + * @param radix 需要转换的进制 + * @return 返回一个多级的Json字符串 + */ + public static String monolayerToJson(JsonNode jsonNode, int radix) { + + ObjectNode resultJson = MAPPER.createObjectNode(); + jsonNode.fields().forEachRemaining(entry -> + parseKeyToMap(resultJson, parseKey(entry.getKey()), entry.getValue(), radix)); + return resultJson.toString(); + } + + /* + * 将平级的key转换成多级key. + */ + private static LinkedList parseKey(String keysString) { + + return new LinkedList(Arrays.asList(keysString.split("\\" + KEY_CHAR))); + } + + /* + * 将平级key对应的数据还原到多级JsonNode中. + */ + private static void parseKeyToMap( + ObjectNode resultJson, + LinkedList keyList, + JsonNode value, + int radix) { + + String key = keyList.removeFirst(); + List indexList = getIndexList(key); + if (indexList.size() > 0) { //说明匹配到数组 + addArray(resultJson, getReallyKey(key), indexList, value, keyList, radix); + } else { + addObject(resultJson, key, value, keyList, radix); + } + } + + /* + * 提取集合key中真正的key. + */ + private static String getReallyKey(String arrayKey) { + + Matcher matcher = PATTERN_KEY.matcher(arrayKey); + String reallyKey = StringUtils.EMPTY; + if (matcher.find()) { + reallyKey = matcher.group(); + } + return reallyKey; + } + + /* + * 将数据还原到Object中. + */ + private static void addObject( + ObjectNode resultJson, + String key, + JsonNode value, + LinkedList keyList, + int radix) { + + //说明为最后一个元素 + if (keyList.size() == 0) { + buildValue(resultJson, key, value, ConvertType.DECIMAL_TO_STRING, radix); + return; + } + if (!resultJson.has(key)) { + resultJson.putObject(key); + } + parseKeyToMap((ObjectNode) resultJson.get(key), keyList, value, radix); + } + + /* + * 将数据还原到Array中. + */ + private static void addArray( + ObjectNode resultJson, + String reallyKey, + List indexList, + JsonNode value, + LinkedList keyList, + int radix) { + + if (!resultJson.has(reallyKey)) { + resultJson.putArray(reallyKey); + } + putArrayValue((ArrayNode) resultJson.get(reallyKey), 0, indexList, value, keyList, radix); + } + + /* + * 处理集合数据. + */ + private static void putArrayValue( + ArrayNode jsonArray, + int level, + List indexList, + JsonNode value, + LinkedList keyList, + int radix) { + + //说明是最底层 + if (level == indexList.size() - 1) { + //说明当前集合长度不够 + if (jsonArray.size() - 1 < indexList.get(level)) { + IntStream.range(0, indexList.get(level) + 1 - jsonArray.size()) + .forEach(i -> jsonArray.addObject()); + } + //下层直接为数据 + if (keyList.size() == 0) { + jsonArray.set(indexList.get(level), + new POJONode(decimalToString(value.asText(), radix))); + } else { + //说明下层有Map + JsonNode jsonObj = jsonArray.get(indexList.get(level)); + parseKeyToMap((ObjectNode) jsonObj, keyList, value, radix); + jsonArray.set(indexList.get(level), jsonObj); + } + } else { + //说明下一层还是集合 + if (jsonArray.size() - 1 < indexList.get(level)) { + //说明当前集合长度不够 + IntStream.range(0, indexList.get(level) + 1 - jsonArray.size()) + .forEach(i -> jsonArray.addArray()); + } + putArrayValue( + (ArrayNode) jsonArray.get(indexList.get(level)), + level + 1, + indexList, + value, + keyList, + radix); + } + } + + /* + * 判断集合的层次,返回每一层对应的下标. + */ + private static List getIndexList(String key) { + Matcher matcher = PATTERN_ARRAY.matcher(key); + List indexList = new ArrayList(); + while (matcher.find()) { + indexList.add(Integer.parseInt(matcher.group())); + } + return indexList; + } + + private enum ConvertType { + STRING_TO_DECIMAL, DECIMAL_TO_STRING + } + + +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Base16.java b/src/main/java/com/webank/weid/util/Multibase/Base16.java new file mode 100644 index 00000000..fd91c14c --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Base16.java @@ -0,0 +1,35 @@ +package com.webank.weid.util.Multibase; + +public class Base16 { + public static byte[] decode(String hex) { + if (hex.length() % 2 == 1) + throw new IllegalStateException("Must have an even number of hex digits to convert to bytes!"); + byte[] res = new byte[hex.length()/2]; + for (int i=0; i < res.length; i++) + res[i] = (byte) Integer.parseInt(hex.substring(2*i, 2*i+2), 16); + return res; + } + + public static String encode(byte[] data) { + return bytesToHex(data); + } + + private static String[] HEX_DIGITS = new String[]{ + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; + private static String[] HEX = new String[256]; + static { + for (int i=0; i < 256; i++) + HEX[i] = HEX_DIGITS[(i >> 4) & 0xF] + HEX_DIGITS[i & 0xF]; + } + + public static String byteToHex(byte b) { + return HEX[b & 0xFF]; + } + + public static String bytesToHex(byte[] data) { + StringBuilder s = new StringBuilder(); + for (byte b : data) + s.append(byteToHex(b)); + return s.toString(); + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Base32.java b/src/main/java/com/webank/weid/util/Multibase/Base32.java new file mode 100644 index 00000000..d863e80c --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Base32.java @@ -0,0 +1,547 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + + +/** + * Provides Base32 encoding and decoding as defined by RFC 4648. + * + * From https://commons.apache.org/proper/commons-codec/ + * + *

+ * The class can be parameterized in the following manner with various constructors: + *

+ *
    + *
  • Whether to use the "base32hex" variant instead of the default "base32"
  • + *
  • Line length: Default 76. Line length that aren't multiples of 8 will still essentially end up being multiples of + * 8 in the encoded data. + *
  • Line separator: Default is CRLF ("\r\n")
  • + *
+ *

+ * This class operates directly on byte streams, and not character streams. + *

+ *

+ * This class is thread-safe. + *

+ * + * @see RFC 4648 + * + * @since 1.5 + * @version $Id$ + */ +public class Base32 extends BaseNCodec { + + /** + * BASE32 characters are 5 bits in length. + * They are formed by taking a block of five octets to form a 40-bit string, + * which is converted into eight BASE32 characters. + */ + private static final int BITS_PER_ENCODED_BYTE = 5; + private static final int BYTES_PER_ENCODED_BLOCK = 8; + private static final int BYTES_PER_UNENCODED_BLOCK = 5; + + /** + * Chunk separator per RFC 2045 section 2.1. + * + * @see RFC 2045 section 2.1 + */ + private static final byte[] CHUNK_SEPARATOR = {'\r', '\n'}; + + /** + * This array is a lookup table that translates Unicode characters drawn from the "Base32 Alphabet" (as specified + * in Table 3 of RFC 4648) into their 5-bit positive integer equivalents. Characters that are not in the Base32 + * alphabet but fall within the bounds of the array are translated to -1. + */ + private static final byte[] DECODE_TABLE = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f + -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, // 30-3f 2-7 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-O + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 50-5a P-Z + -1, -1, -1, -1, -1, // 5b - 5f + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 60 - 6f a-o + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 70 - 7a p-z/**/ + }; + + /** + * This array is a lookup table that translates 5-bit positive integer index values into their "Base32 Alphabet" + * equivalents as specified in Table 3 of RFC 4648. + */ + private static final byte[] ENCODE_TABLE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '2', '3', '4', '5', '6', '7', + }; + + /** + * This array is a lookup table that translates Unicode characters drawn from the "Base32 Hex Alphabet" (as + * specified in Table 4 of RFC 4648) into their 5-bit positive integer equivalents. Characters that are not in the + * Base32 Hex alphabet but fall within the bounds of the array are translated to -1. + */ + private static final byte[] HEX_DECODE_TABLE = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30-3f 2-7 + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 40-4f A-O + 25, 26, 27, 28, 29, 30, 31, // 50-56 P-V + -1, -1, -1, -1, -1, -1, -1, -1, -1, // 57-5f Z-_ + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 60-6f `-o + 25, 26, 27, 28, 29, 30, 31 // 70-76 p-v + }; + + /** + * This array is a lookup table that translates 5-bit positive integer index values into their + * "Base32 Hex Alphabet" equivalents as specified in Table 4 of RFC 4648. + */ + private static final byte[] HEX_ENCODE_TABLE = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + }; + + /** Mask used to extract 5 bits, used when encoding Base32 bytes */ + private static final int MASK_5BITS = 0x1f; + + // The static final fields above are used for the original static byte[] methods on Base32. + // The private member fields below are used with the new streaming approach, which requires + // some state be preserved between calls of encode() and decode(). + + /** + * Place holder for the bytes we're dealing with for our based logic. + * Bitwise operations store and extract the encoding or decoding from this variable. + */ + + /** + * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. + * decodeSize = {@link #BYTES_PER_ENCODED_BLOCK} - 1 + lineSeparator.length; + */ + private final int decodeSize; + + /** + * Decode table to use. + */ + private final byte[] decodeTable; + + /** + * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. + * encodeSize = {@link #BYTES_PER_ENCODED_BLOCK} + lineSeparator.length; + */ + private final int encodeSize; + + /** + * Encode table to use. + */ + private final byte[] encodeTable; + + /** + * Line separator for encoding. Not used when decoding. Only used if lineLength > 0. + */ + private final byte[] lineSeparator; + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length is 0 (no chunking). + *

+ * + */ + public Base32() { + this(false); + } + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length is 0 (no chunking). + *

+ * @param pad byte used as padding byte. + */ + public Base32(final byte pad) { + this(false, pad); + } + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length is 0 (no chunking). + *

+ * @param useHex if {@code true} then use Base32 Hex alphabet + */ + public Base32(final boolean useHex) { + this(0, null, useHex, PAD_DEFAULT); + } + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length is 0 (no chunking). + *

+ * @param useHex if {@code true} then use Base32 Hex alphabet + * @param pad byte used as padding byte. + */ + public Base32(final boolean useHex, final byte pad) { + this(0, null, useHex, pad); + } + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length is given in the constructor, the line separator is CRLF. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 8). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + */ + public Base32(final int lineLength) { + this(lineLength, CHUNK_SEPARATOR); + } + + /** + * Creates a Base32 codec used for decoding and encoding. + *

+ * When encoding the line length and line separator are given in the constructor. + *

+ *

+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 8). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @param lineSeparator + * Each line of encoded data will end with this sequence of bytes. + * @throws IllegalArgumentException + * The provided lineSeparator included some Base32 characters. That's not going to work! + */ + public Base32(final int lineLength, final byte[] lineSeparator) { + this(lineLength, lineSeparator, false, PAD_DEFAULT); + } + + /** + * Creates a Base32 / Base32 Hex codec used for decoding and encoding. + *

+ * When encoding the line length and line separator are given in the constructor. + *

+ *

+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 8). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @param lineSeparator + * Each line of encoded data will end with this sequence of bytes. + * @param useHex + * if {@code true}, then use Base32 Hex alphabet, otherwise use Base32 alphabet + * @throws IllegalArgumentException + * The provided lineSeparator included some Base32 characters. That's not going to work! Or the + * lineLength > 0 and lineSeparator is null. + */ + public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex) { + this(lineLength, lineSeparator, useHex, PAD_DEFAULT); + } + + /** + * Creates a Base32 / Base32 Hex codec used for decoding and encoding. + *

+ * When encoding the line length and line separator are given in the constructor. + *

+ *

+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 8). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @param lineSeparator + * Each line of encoded data will end with this sequence of bytes. + * @param useHex + * if {@code true}, then use Base32 Hex alphabet, otherwise use Base32 alphabet + * @param pad byte used as padding byte. + * @throws IllegalArgumentException + * The provided lineSeparator included some Base32 characters. That's not going to work! Or the + * lineLength > 0 and lineSeparator is null. + */ + public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte pad) { + super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, + lineSeparator == null ? 0 : lineSeparator.length, pad); + if (useHex) { + this.encodeTable = HEX_ENCODE_TABLE; + this.decodeTable = HEX_DECODE_TABLE; + } else { + this.encodeTable = ENCODE_TABLE; + this.decodeTable = DECODE_TABLE; + } + if (lineLength > 0) { + if (lineSeparator == null) { + throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null"); + } + // Must be done after initializing the tables + if (containsAlphabetOrPad(lineSeparator)) { + final String sep = StringUtils.newStringUtf8(lineSeparator); + throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]"); + } + this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length; + this.lineSeparator = new byte[lineSeparator.length]; + System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length); + } else { + this.encodeSize = BYTES_PER_ENCODED_BLOCK; + this.lineSeparator = null; + } + this.decodeSize = this.encodeSize - 1; + + if (isInAlphabet(pad) || isWhiteSpace(pad)) { + throw new IllegalArgumentException("pad must not be in alphabet or whitespace"); + } + } + + /** + *

+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once + * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1" + * call is not necessary when decoding, but it doesn't hurt, either. + *

+ *

+ * Ignores all non-Base32 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are + * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in, + * garbage-out philosophy: it will not check the provided data for validity. + *

+ * + * @param in + * byte[] array of ascii data to Base32 decode. + * @param inPos + * Position to start reading data from. + * @param inAvail + * Amount of bytes available from input for encoding. + * @param context the context to be used + * + * Output is written to {@link Context#buffer} as 8-bit octets, using {@link Context#pos} as the buffer position + */ + @Override + void decode(final byte[] in, int inPos, final int inAvail, final Context context) { + // package protected for access from I/O streams + + if (context.eof) { + return; + } + if (inAvail < 0) { + context.eof = true; + } + for (int i = 0; i < inAvail; i++) { + final byte b = in[inPos++]; + if (b == pad) { + // We're done. + context.eof = true; + break; + } + final byte[] buffer = ensureBufferSize(decodeSize, context); + if (b >= 0 && b < this.decodeTable.length) { + final int result = this.decodeTable[b]; + if (result >= 0) { + context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK; + // collect decoded bytes + context.lbitWorkArea = (context.lbitWorkArea << BITS_PER_ENCODED_BYTE) + result; + if (context.modulus == 0) { // we can output the 5 bytes + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 32) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS); + } + } + } + } + + // Two forms of EOF as far as Base32 decoder is concerned: actual + // EOF (-1) and first time '=' character is encountered in stream. + // This approach makes the '=' padding characters completely optional. + if (context.eof && context.modulus >= 2) { // if modulus < 2, nothing to do + final byte[] buffer = ensureBufferSize(decodeSize, context); + + // we ignore partial bytes, i.e. only multiples of 8 count + switch (context.modulus) { + case 2 : // 10 bits, drop 2 and output one byte + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 2) & MASK_8BITS); + break; + case 3 : // 15 bits, drop 7 and output 1 byte + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 7) & MASK_8BITS); + break; + case 4 : // 20 bits = 2*8 + 4 + context.lbitWorkArea = context.lbitWorkArea >> 4; // drop 4 bits + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); + break; + case 5 : // 25bits = 3*8 + 1 + context.lbitWorkArea = context.lbitWorkArea >> 1; + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); + break; + case 6 : // 30bits = 3*8 + 6 + context.lbitWorkArea = context.lbitWorkArea >> 6; + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); + break; + case 7 : // 35 = 4*8 +3 + context.lbitWorkArea = context.lbitWorkArea >> 3; + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); + break; + default: + // modulus can be 0-7, and we excluded 0,1 already + throw new IllegalStateException("Impossible modulus "+context.modulus); + } + } + } + + /** + *

+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with + * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last + * remaining bytes (if not multiple of 5). + *

+ * + * @param in + * byte[] array of binary data to Base32 encode. + * @param inPos + * Position to start reading data from. + * @param inAvail + * Amount of bytes available from input for encoding. + * @param context the context to be used + */ + @Override + void encode(final byte[] in, int inPos, final int inAvail, final Context context) { + // package protected for access from I/O streams + + if (context.eof) { + return; + } + // inAvail < 0 is how we're informed of EOF in the underlying data we're + // encoding. + if (inAvail < 0) { + context.eof = true; + if (0 == context.modulus && lineLength == 0) { + return; // no leftovers to process and not using chunking + } + final byte[] buffer = ensureBufferSize(encodeSize, context); + final int savedPos = context.pos; + switch (context.modulus) { // % 5 + case 0 : + break; + case 1 : // Only 1 octet; take top 5 bits then remainder + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 3) & MASK_5BITS]; // 8-1*5 = 3 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 2) & MASK_5BITS]; // 5-3=2 + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + break; + case 2 : // 2 octets = 16 bits to use + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 11) & MASK_5BITS]; // 16-1*5 = 11 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 6) & MASK_5BITS]; // 16-2*5 = 6 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 1) & MASK_5BITS]; // 16-3*5 = 1 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 4) & MASK_5BITS]; // 5-1 = 4 + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + break; + case 3 : // 3 octets = 24 bits to use + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 19) & MASK_5BITS]; // 24-1*5 = 19 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 14) & MASK_5BITS]; // 24-2*5 = 14 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 9) & MASK_5BITS]; // 24-3*5 = 9 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 4) & MASK_5BITS]; // 24-4*5 = 4 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 1) & MASK_5BITS]; // 5-4 = 1 + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + break; + case 4 : // 4 octets = 32 bits to use + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 27) & MASK_5BITS]; // 32-1*5 = 27 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 22) & MASK_5BITS]; // 32-2*5 = 22 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 17) & MASK_5BITS]; // 32-3*5 = 17 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 12) & MASK_5BITS]; // 32-4*5 = 12 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 7) & MASK_5BITS]; // 32-5*5 = 7 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 2) & MASK_5BITS]; // 32-6*5 = 2 + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 3) & MASK_5BITS]; // 5-2 = 3 + buffer[context.pos++] = pad; + break; + default: + throw new IllegalStateException("Impossible modulus "+context.modulus); + } + context.currentLinePos += context.pos - savedPos; // keep track of current line position + // if currentPos == 0 we are at the start of a line, so don't add CRLF + if (lineLength > 0 && context.currentLinePos > 0){ // add chunk separator if required + System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); + context.pos += lineSeparator.length; + } + } else { + for (int i = 0; i < inAvail; i++) { + final byte[] buffer = ensureBufferSize(encodeSize, context); + context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK; + int b = in[inPos++]; + if (b < 0) { + b += 256; + } + context.lbitWorkArea = (context.lbitWorkArea << 8) + b; // BITS_PER_BYTE + if (0 == context.modulus) { // we have enough bytes to create our output + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 35) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 30) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 25) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 20) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 15) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 10) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 5) & MASK_5BITS]; + buffer[context.pos++] = encodeTable[(int)context.lbitWorkArea & MASK_5BITS]; + context.currentLinePos += BYTES_PER_ENCODED_BLOCK; + if (lineLength > 0 && lineLength <= context.currentLinePos) { + System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); + context.pos += lineSeparator.length; + context.currentLinePos = 0; + } + } + } + } + } + + /** + * Returns whether or not the {@code octet} is in the Base32 alphabet. + * + * @param octet + * The value to test + * @return {@code true} if the value is defined in the the Base32 alphabet {@code false} otherwise. + */ + @Override + public boolean isInAlphabet(final byte octet) { + return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1; + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Base36.java b/src/main/java/com/webank/weid/util/Multibase/Base36.java new file mode 100644 index 00000000..d58f1e8d --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Base36.java @@ -0,0 +1,42 @@ +package com.webank.weid.util.Multibase; + +import java.math.*; + +public class Base36 { + + public static byte[] decode(String in) { + byte[] withoutLeadingZeroes = new BigInteger(in, 36).toByteArray(); + int zeroPrefixLength = zeroPrefixLength(in); + byte[] res = new byte[zeroPrefixLength + withoutLeadingZeroes.length]; + System.arraycopy(withoutLeadingZeroes, 0, res, zeroPrefixLength, withoutLeadingZeroes.length); + return res; + } + + public static String encode(byte[] in) { + String withoutLeadingZeroes = new BigInteger(1, in).toString(36); + int zeroPrefixLength = zeroPrefixLength(in); + StringBuilder b = new StringBuilder(); + for (int i=0; i < zeroPrefixLength; i++) + b.append("0"); + b.append(withoutLeadingZeroes); + return b.toString(); + } + + private static int zeroPrefixLength(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] != 0) { + return i; + } + } + return bytes.length; + } + + private static int zeroPrefixLength(String in) { + for (int i = 0; i < in.length(); i++) { + if (in.charAt(i) != '0') { + return i; + } + } + return in.length(); + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Base58.java b/src/main/java/com/webank/weid/util/Multibase/Base58.java new file mode 100644 index 00000000..9174d742 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Base58.java @@ -0,0 +1,162 @@ +package com.webank.weid.util.Multibase; + +/* + * Copyright 2011 Google Inc. + * Copyright 2018 Andreas Schildbach + * + * From https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/core/Base58.java + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.math.BigInteger; +import java.util.Arrays; + +/** + * Base58 is a way to encode Bitcoin addresses (or arbitrary data) as alphanumeric strings. + *

+ * Note that this is not the same base58 as used by Flickr, which you may find referenced around the Internet. + *

+ * Satoshi explains: why base-58 instead of standard base-64 encoding? + *

    + *
  • Don't want 0OIl characters that look the same in some fonts and + * could be used to create visually identical looking account numbers.
  • + *
  • A string with non-alphanumeric characters is not as easily accepted as an account number.
  • + *
  • E-mail usually won't line-break if there's no punctuation to break at.
  • + *
  • Doubleclicking selects the whole number as one word if it's all alphanumeric.
  • + *
+ *

+ * However, note that the encoding/decoding runs in O(n²) time, so it is not useful for large data. + *

+ * The basic idea of the encoding is to treat the data bytes as a large number represented using + * base-256 digits, convert the number to be represented using base-58 digits, preserve the exact + * number of leading zeros (which are otherwise lost during the mathematical operations on the + * numbers), and finally represent the resulting base-58 digits as alphanumeric ASCII characters. + */ +public class Base58 { + public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + private static final char ENCODED_ZERO = ALPHABET[0]; + private static final int[] INDEXES = new int[128]; + static { + Arrays.fill(INDEXES, -1); + for (int i = 0; i < ALPHABET.length; i++) { + INDEXES[ALPHABET[i]] = i; + } + } + + /** + * Encodes the given bytes as a base58 string (no checksum is appended). + * + * @param input the bytes to encode + * @return the base58-encoded string + */ + public static String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input.length && input[zeros] == 0) { + ++zeros; + } + // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) + input = Arrays.copyOf(input, input.length); // since we modify it in-place + char[] encoded = new char[input.length * 2]; // upper bound + int outputStart = encoded.length; + for (int inputStart = zeros; inputStart < input.length; ) { + encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)]; + if (input[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. + while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) { + ++outputStart; + } + while (--zeros >= 0) { + encoded[--outputStart] = ENCODED_ZERO; + } + // Return encoded string (including encoded leading zeros). + return new String(encoded, outputStart, encoded.length - outputStart); + } + + /** + * Decodes the given base58 string into the original data bytes. + * + * @param input the base58-encoded string to decode + * @return the decoded data bytes + */ + public static byte[] decode(String input) { + if (input.length() == 0) { + return new byte[0]; + } + // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). + byte[] input58 = new byte[input.length()]; + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + int digit = c < 128 ? INDEXES[c] : -1; + if (digit < 0) { + throw new IllegalStateException("InvalidCharacter in base 58"); + } + input58[i] = (byte) digit; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input58.length && input58[zeros] == 0) { + ++zeros; + } + // Convert base-58 digits to base-256 digits. + byte[] decoded = new byte[input.length()]; + int outputStart = decoded.length; + for (int inputStart = zeros; inputStart < input58.length; ) { + decoded[--outputStart] = divmod(input58, inputStart, 58, 256); + if (input58[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Ignore extra leading zeroes that were added during the calculation. + while (outputStart < decoded.length && decoded[outputStart] == 0) { + ++outputStart; + } + // Return decoded data (including original number of leading zeros). + return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); + } + + public static BigInteger decodeToBigInteger(String input) { + return new BigInteger(1, decode(input)); + } + + /** + * Divides a number, represented as an array of bytes each containing a single digit + * in the specified base, by the given divisor. The given number is modified in-place + * to contain the quotient, and the return value is the remainder. + * + * @param number the number to divide + * @param firstDigit the index within the array of the first non-zero digit + * (this is used for optimization by skipping the leading zeros) + * @param base the base in which the number's digits are represented (up to 256) + * @param divisor the number to divide by (up to 256) + * @return the remainder of the division operation + */ + private static byte divmod(byte[] number, int firstDigit, int base, int divisor) { + // this is just long division which accounts for the base of the input digits + int remainder = 0; + for (int i = firstDigit; i < number.length; i++) { + int digit = (int) number[i] & 0xFF; + int temp = remainder * base + digit; + number[i] = (byte) (temp / divisor); + remainder = temp % divisor; + } + return (byte) remainder; + } +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/util/Multibase/Base64.java b/src/main/java/com/webank/weid/util/Multibase/Base64.java new file mode 100644 index 00000000..ee77ef85 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Base64.java @@ -0,0 +1,787 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +import java.math.BigInteger; + +/** + * Provides Base64 encoding and decoding as defined by RFC 2045. + * + * From https://commons.apache.org/proper/commons-codec/ + * + *

+ * This class implements section 6.8. Base64 Content-Transfer-Encoding from RFC 2045 Multipurpose + * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies by Freed and Borenstein. + *

+ *

+ * The class can be parameterized in the following manner with various constructors: + *

+ *
    + *
  • URL-safe mode: Default off.
  • + *
  • Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of + * 4 in the encoded data. + *
  • Line separator: Default is CRLF ("\r\n")
  • + *
+ *

+ * The URL-safe parameter is only applied to encode operations. Decoding seamlessly handles both modes. + *

+ *

+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only + * encode/decode character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, + * UTF-8, etc). + *

+ *

+ * This class is thread-safe. + *

+ * + * @see RFC 2045 + * @since 1.0 + * @version $Id$ + */ +public class Base64 extends BaseNCodec { + + /** + * BASE32 characters are 6 bits in length. + * They are formed by taking a block of 3 octets to form a 24-bit string, + * which is converted into 4 BASE64 characters. + */ + private static final int BITS_PER_ENCODED_BYTE = 6; + private static final int BYTES_PER_UNENCODED_BLOCK = 3; + private static final int BYTES_PER_ENCODED_BLOCK = 4; + + /** + * Chunk separator per RFC 2045 section 2.1. + * + *

+ * N.B. The next major release may break compatibility and make this field private. + *

+ * + * @see RFC 2045 section 2.1 + */ + static final byte[] CHUNK_SEPARATOR = {'\r', '\n'}; + + /** + * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet" + * equivalents as specified in Table 1 of RFC 2045. + * + * Thanks to "commons" project in ws.apache.org for this code. + * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ + */ + private static final byte[] STANDARD_ENCODE_TABLE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + /** + * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / + * changed to - and _ to make the encoded Base64 results more URL-SAFE. + * This table is only used when the Base64's mode is set to URL-SAFE. + */ + private static final byte[] URL_SAFE_ENCODE_TABLE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + /** + * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified + * in Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64 + * alphabet but fall within the bounds of the array are translated to -1. + * + * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both + * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit). + * + * Thanks to "commons" project in ws.apache.org for this code. + * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ + */ + private static final byte[] DECODE_TABLE = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, // 20-2f + - / + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-O + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _ + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 70-7a p-z + }; + + /** + * Base64 uses 6-bit fields. + */ + /** Mask used to extract 6 bits, used when encoding */ + private static final int MASK_6BITS = 0x3f; + + // The static final fields above are used for the original static byte[] methods on Base64. + // The private member fields below are used with the new streaming approach, which requires + // some state be preserved between calls of encode() and decode(). + + /** + * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able + * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch + * between the two modes. + */ + private final byte[] encodeTable; + + // Only one decode table currently; keep for consistency with Base32 code + private final byte[] decodeTable = DECODE_TABLE; + + /** + * Line separator for encoding. Not used when decoding. Only used if lineLength > 0. + */ + private final byte[] lineSeparator; + + /** + * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. + * decodeSize = 3 + lineSeparator.length; + */ + private final int decodeSize; + + /** + * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. + * encodeSize = 4 + lineSeparator.length; + */ + private final int encodeSize; + + /** + * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. + *

+ * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE. + *

+ * + *

+ * When decoding all variants are supported. + *

+ */ + public Base64() { + this(0); + } + + /** + * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode. + *

+ * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE. + *

+ * + *

+ * When decoding all variants are supported. + *

+ * + * @param urlSafe + * if true, URL-safe encoding is used. In most cases this should be set to + * false. + * @since 1.4 + */ + public Base64(final boolean urlSafe) { + this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe); + } + + /** + * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. + *

+ * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is + * STANDARD_ENCODE_TABLE. + *

+ *

+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. + *

+ *

+ * When decoding all variants are supported. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @since 1.4 + */ + public Base64(final int lineLength) { + this(lineLength, CHUNK_SEPARATOR); + } + + /** + * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. + *

+ * When encoding the line length and line separator are given in the constructor, and the encoding table is + * STANDARD_ENCODE_TABLE. + *

+ *

+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. + *

+ *

+ * When decoding all variants are supported. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @param lineSeparator + * Each line of encoded data will end with this sequence of bytes. + * @throws IllegalArgumentException + * Thrown when the provided lineSeparator included some base64 characters. + * @since 1.4 + */ + public Base64(final int lineLength, final byte[] lineSeparator) { + this(lineLength, lineSeparator, false); + } + + /** + * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. + *

+ * When encoding the line length and line separator are given in the constructor, and the encoding table is + * STANDARD_ENCODE_TABLE. + *

+ *

+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. + *

+ *

+ * When decoding all variants are supported. + *

+ * + * @param lineLength + * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of + * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when + * decoding. + * @param lineSeparator + * Each line of encoded data will end with this sequence of bytes. + * @param urlSafe + * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode + * operations. Decoding seamlessly handles both modes. + * Note: no padding is added when using the URL-safe alphabet. + * @throws IllegalArgumentException + * The provided lineSeparator included some base64 characters. That's not going to work! + * @since 1.4 + */ + public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) { + super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, + lineLength, + lineSeparator == null ? 0 : lineSeparator.length); + // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0 + // @see test case Base64Test.testConstructors() + if (lineSeparator != null) { + if (containsAlphabetOrPad(lineSeparator)) { + final String sep = StringUtils.newStringUtf8(lineSeparator); + throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]"); + } + if (lineLength > 0){ // null line-sep forces no chunking rather than throwing IAE + this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length; + this.lineSeparator = new byte[lineSeparator.length]; + System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length); + } else { + this.encodeSize = BYTES_PER_ENCODED_BLOCK; + this.lineSeparator = null; + } + } else { + this.encodeSize = BYTES_PER_ENCODED_BLOCK; + this.lineSeparator = null; + } + this.decodeSize = this.encodeSize - 1; + this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE; + } + + /** + * Returns our current encode mode. True if we're URL-SAFE, false otherwise. + * + * @return true if we're in URL-SAFE mode, false otherwise. + * @since 1.4 + */ + public boolean isUrlSafe() { + return this.encodeTable == URL_SAFE_ENCODE_TABLE; + } + + /** + *

+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with + * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, to flush last + * remaining bytes (if not multiple of 3). + *

+ *

Note: no padding is added when encoding using the URL-safe alphabet.

+ *

+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach. + * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ + *

+ * + * @param in + * byte[] array of binary data to base64 encode. + * @param inPos + * Position to start reading data from. + * @param inAvail + * Amount of bytes available from input for encoding. + * @param context + * the context to be used + */ + @Override + void encode(final byte[] in, int inPos, final int inAvail, final Context context) { + if (context.eof) { + return; + } + // inAvail < 0 is how we're informed of EOF in the underlying data we're + // encoding. + if (inAvail < 0) { + context.eof = true; + if (0 == context.modulus && lineLength == 0) { + return; // no leftovers to process and not using chunking + } + final byte[] buffer = ensureBufferSize(encodeSize, context); + final int savedPos = context.pos; + switch (context.modulus) { // 0-2 + case 0 : // nothing to do here + break; + case 1 : // 8 bits = 6 + 2 + // top 6 bits: + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 2) & MASK_6BITS]; + // remaining 2: + buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 4) & MASK_6BITS]; + // URL-SAFE skips the padding to further reduce size. + if (encodeTable == STANDARD_ENCODE_TABLE) { + buffer[context.pos++] = pad; + buffer[context.pos++] = pad; + } + break; + + case 2 : // 16 bits = 6 + 6 + 4 + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 10) & MASK_6BITS]; + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 4) & MASK_6BITS]; + buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 2) & MASK_6BITS]; + // URL-SAFE skips the padding to further reduce size. + if (encodeTable == STANDARD_ENCODE_TABLE) { + buffer[context.pos++] = pad; + } + break; + default: + throw new IllegalStateException("Impossible modulus "+context.modulus); + } + context.currentLinePos += context.pos - savedPos; // keep track of current line position + // if currentPos == 0 we are at the start of a line, so don't add CRLF + if (lineLength > 0 && context.currentLinePos > 0) { + System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); + context.pos += lineSeparator.length; + } + } else { + for (int i = 0; i < inAvail; i++) { + final byte[] buffer = ensureBufferSize(encodeSize, context); + context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK; + int b = in[inPos++]; + if (b < 0) { + b += 256; + } + context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE + if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 18) & MASK_6BITS]; + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 12) & MASK_6BITS]; + buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 6) & MASK_6BITS]; + buffer[context.pos++] = encodeTable[context.ibitWorkArea & MASK_6BITS]; + context.currentLinePos += BYTES_PER_ENCODED_BLOCK; + if (lineLength > 0 && lineLength <= context.currentLinePos) { + System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); + context.pos += lineSeparator.length; + context.currentLinePos = 0; + } + } + } + } + } + + /** + *

+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once + * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1" + * call is not necessary when decoding, but it doesn't hurt, either. + *

+ *

+ * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are + * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in, + * garbage-out philosophy: it will not check the provided data for validity. + *

+ *

+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach. + * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ + *

+ * + * @param in + * byte[] array of ascii data to base64 decode. + * @param inPos + * Position to start reading data from. + * @param inAvail + * Amount of bytes available from input for encoding. + * @param context + * the context to be used + */ + @Override + void decode(final byte[] in, int inPos, final int inAvail, final Context context) { + if (context.eof) { + return; + } + if (inAvail < 0) { + context.eof = true; + } + for (int i = 0; i < inAvail; i++) { + final byte[] buffer = ensureBufferSize(decodeSize, context); + final byte b = in[inPos++]; + if (b == pad) { + // We're done. + context.eof = true; + break; + } + if (b >= 0 && b < DECODE_TABLE.length) { + final int result = DECODE_TABLE[b]; + if (result >= 0) { + context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK; + context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result; + if (context.modulus == 0) { + buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 16) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS); + } + } + } + } + + // Two forms of EOF as far as base64 decoder is concerned: actual + // EOF (-1) and first time '=' character is encountered in stream. + // This approach makes the '=' padding characters completely optional. + if (context.eof && context.modulus != 0) { + final byte[] buffer = ensureBufferSize(decodeSize, context); + + // We have some spare bits remaining + // Output all whole multiples of 8 bits and ignore the rest + switch (context.modulus) { +// case 0 : // impossible, as excluded above + case 1 : // 6 bits - ignore entirely + // TODO not currently tested; perhaps it is impossible? + break; + case 2 : // 12 bits = 8 + 4 + context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits + buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS); + break; + case 3 : // 18 bits = 8 + 8 + 2 + context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits + buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS); + buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS); + break; + default: + throw new IllegalStateException("Impossible modulus "+context.modulus); + } + } + } + + /** + * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the + * method treats whitespace as valid. + * + * @param arrayOctet + * byte array to test + * @return true if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; + * false, otherwise + * @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0. + */ + @Deprecated + public static boolean isArrayByteBase64(final byte[] arrayOctet) { + return isBase64(arrayOctet); + } + + /** + * Returns whether or not the octet is in the base 64 alphabet. + * + * @param octet + * The value to test + * @return true if the value is defined in the the base 64 alphabet, false otherwise. + * @since 1.4 + */ + public static boolean isBase64(final byte octet) { + return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1); + } + + /** + * Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the + * method treats whitespace as valid. + * + * @param base64 + * String to test + * @return true if all characters in the String are valid characters in the Base64 alphabet or if + * the String is empty; false, otherwise + * @since 1.5 + */ + public static boolean isBase64(final String base64) { + return isBase64(StringUtils.getBytesUtf8(base64)); + } + + /** + * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the + * method treats whitespace as valid. + * + * @param arrayOctet + * byte array to test + * @return true if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; + * false, otherwise + * @since 1.5 + */ + public static boolean isBase64(final byte[] arrayOctet) { + for (int i = 0; i < arrayOctet.length; i++) { + if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) { + return false; + } + } + return true; + } + + /** + * Encodes binary data using the base64 algorithm but does not chunk the output. + * + * @param binaryData + * binary data to encode + * @return byte[] containing Base64 characters in their UTF-8 representation. + */ + public static byte[] encodeBase64(final byte[] binaryData) { + return encodeBase64(binaryData, false); + } + + /** + * Encodes binary data using the base64 algorithm but does not chunk the output. + * + * NOTE: We changed the behaviour of this method from multi-line chunking (commons-codec-1.4) to + * single-line non-chunking (commons-codec-1.5). + * + * @param binaryData + * binary data to encode + * @return String containing Base64 characters. + * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not). + */ + public static String encodeBase64String(final byte[] binaryData) { + return StringUtils.newStringUsAscii(encodeBase64(binaryData, false)); + } + + /** + * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The + * url-safe variation emits - and _ instead of + and / characters. + * Note: no padding is added. + * @param binaryData + * binary data to encode + * @return byte[] containing Base64 characters in their UTF-8 representation. + * @since 1.4 + */ + public static byte[] encodeBase64URLSafe(final byte[] binaryData) { + return encodeBase64(binaryData, false, true); + } + + /** + * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The + * url-safe variation emits - and _ instead of + and / characters. + * Note: no padding is added. + * @param binaryData + * binary data to encode + * @return String containing Base64 characters + * @since 1.4 + */ + public static String encodeBase64URLSafeString(final byte[] binaryData) { + return StringUtils.newStringUsAscii(encodeBase64(binaryData, false, true)); + } + + /** + * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks + * + * @param binaryData + * binary data to encode + * @return Base64 characters chunked in 76 character blocks + */ + public static byte[] encodeBase64Chunked(final byte[] binaryData) { + return encodeBase64(binaryData, true); + } + + /** + * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. + * + * @param binaryData + * Array containing binary data to encode. + * @param isChunked + * if true this encoder will chunk the base64 output into 76 character blocks + * @return Base64-encoded data. + * @throws IllegalArgumentException + * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} + */ + public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) { + return encodeBase64(binaryData, isChunked, false); + } + + /** + * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. + * + * @param binaryData + * Array containing binary data to encode. + * @param isChunked + * if true this encoder will chunk the base64 output into 76 character blocks + * @param urlSafe + * if true this encoder will emit - and _ instead of the usual + and / characters. + * Note: no padding is added when encoding using the URL-safe alphabet. + * @return Base64-encoded data. + * @throws IllegalArgumentException + * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} + * @since 1.4 + */ + public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) { + return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE); + } + + /** + * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. + * + * @param binaryData + * Array containing binary data to encode. + * @param isChunked + * if true this encoder will chunk the base64 output into 76 character blocks + * @param urlSafe + * if true this encoder will emit - and _ instead of the usual + and / characters. + * Note: no padding is added when encoding using the URL-safe alphabet. + * @param maxResultSize + * The maximum result size to accept. + * @return Base64-encoded data. + * @throws IllegalArgumentException + * Thrown when the input array needs an output array bigger than maxResultSize + * @since 1.4 + */ + public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, + final boolean urlSafe, final int maxResultSize) { + if (binaryData == null || binaryData.length == 0) { + return binaryData; + } + + // Create this so can use the super-class method + // Also ensures that the same roundings are performed by the ctor and the code + final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe); + final long len = b64.getEncodedLength(binaryData); + if (len > maxResultSize) { + throw new IllegalArgumentException("Input array too big, the output array would be bigger (" + + len + + ") than the specified maximum size of " + + maxResultSize); + } + + return b64.encode(binaryData); + } + + /** + * Decodes a Base64 String into octets. + *

+ * Note: this method seamlessly handles data encoded in URL-safe or normal mode. + *

+ * + * @param base64String + * String containing Base64 data + * @return Array containing decoded data. + * @since 1.4 + */ + public static byte[] decodeBase64(final String base64String) { + return new Base64().decode(base64String); + } + + /** + * Decodes Base64 data into octets. + *

+ * Note: this method seamlessly handles data encoded in URL-safe or normal mode. + *

+ * + * @param base64Data + * Byte array containing Base64 data + * @return Array containing decoded data. + */ + public static byte[] decodeBase64(final byte[] base64Data) { + return new Base64().decode(base64Data); + } + + // Implementation of the Encoder Interface + + // Implementation of integer encoding used for crypto + /** + * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature. + * + * @param pArray + * a byte array containing base64 character data + * @return A BigInteger + * @since 1.4 + */ + public static BigInteger decodeInteger(final byte[] pArray) { + return new BigInteger(1, decodeBase64(pArray)); + } + + /** + * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature. + * + * @param bigInt + * a BigInteger + * @return A byte array containing base64 character data + * @throws NullPointerException + * if null is passed in + * @since 1.4 + */ + public static byte[] encodeInteger(final BigInteger bigInt) { + if (bigInt == null) { + throw new NullPointerException("encodeInteger called with null parameter"); + } + return encodeBase64(toIntegerBytes(bigInt), false); + } + + /** + * Returns a byte-array representation of a BigInteger without sign bit. + * + * @param bigInt + * BigInteger to be converted + * @return a byte array representation of the BigInteger parameter + */ + static byte[] toIntegerBytes(final BigInteger bigInt) { + int bitlen = bigInt.bitLength(); + // round bitlen + bitlen = ((bitlen + 7) >> 3) << 3; + final byte[] bigBytes = bigInt.toByteArray(); + + if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) { + return bigBytes; + } + // set up params for copying everything but sign bit + int startSrc = 0; + int len = bigBytes.length; + + // if bigInt is exactly byte-aligned, just skip signbit in copy + if ((bigInt.bitLength() % 8) == 0) { + startSrc = 1; + len--; + } + final int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec + final byte[] resizedBytes = new byte[bitlen / 8]; + System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len); + return resizedBytes; + } + + /** + * Returns whether or not the octet is in the Base64 alphabet. + * + * @param octet + * The value to test + * @return true if the value is defined in the the Base64 alphabet false otherwise. + */ + @Override + protected boolean isInAlphabet(final byte octet) { + return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1; + } + +} diff --git a/src/main/java/com/webank/weid/util/Multibase/BaseNCodec.java b/src/main/java/com/webank/weid/util/Multibase/BaseNCodec.java new file mode 100644 index 00000000..bc70a83d --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/BaseNCodec.java @@ -0,0 +1,528 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Abstract superclass for Base-N encoders and decoders. + * + * From https://commons.apache.org/proper/commons-codec/ + * + *

+ * This class is thread-safe. + *

+ * + * @version $Id$ + */ +public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder { + + /** + * Holds thread context so classes can be thread-safe. + * + * This class is not itself thread-safe; each thread must allocate its own copy. + * + * @since 1.7 + */ + static class Context { + + /** + * Place holder for the bytes we're dealing with for our based logic. + * Bitwise operations store and extract the encoding or decoding from this variable. + */ + int ibitWorkArea; + + /** + * Place holder for the bytes we're dealing with for our based logic. + * Bitwise operations store and extract the encoding or decoding from this variable. + */ + long lbitWorkArea; + + /** + * Buffer for streaming. + */ + byte[] buffer; + + /** + * Position where next character should be written in the buffer. + */ + int pos; + + /** + * Position where next character should be read from the buffer. + */ + int readPos; + + /** + * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless, + * and must be thrown away. + */ + boolean eof; + + /** + * Variable tracks how many characters have been written to the current line. Only used when encoding. We use + * it to make sure each encoded line never goes beyond lineLength (if lineLength > 0). + */ + int currentLinePos; + + /** + * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This + * variable helps track that. + */ + int modulus; + + Context() {} + } + + /** + * EOF + * + * @since 1.7 + */ + static final int EOF = -1; + + /** + * MIME chunk size per RFC 2045 section 6.8. + * + *

+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any + * equal signs. + *

+ * + * @see RFC 2045 section 6.8 + */ + public static final int MIME_CHUNK_SIZE = 76; + + /** + * PEM chunk size per RFC 1421 section 4.3.2.4. + * + *

+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any + * equal signs. + *

+ * + * @see RFC 1421 section 4.3.2.4 + */ + public static final int PEM_CHUNK_SIZE = 64; + + private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2; + + /** + * Defines the default buffer size - currently {@value} + * - must be large enough for at least one encoded block+separator + */ + private static final int DEFAULT_BUFFER_SIZE = 8192; + + /** Mask used to extract 8 bits, used in decoding bytes */ + protected static final int MASK_8BITS = 0xff; + + /** + * Byte used to pad output. + */ + protected static final byte PAD_DEFAULT = '='; // Allow static access to default + + /** + * @deprecated Use {@link #pad}. Will be removed in 2.0. + */ + @Deprecated + protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later + + protected final byte pad; // instance variable just in case it needs to vary later + + /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */ + private final int unencodedBlockSize; + + /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */ + private final int encodedBlockSize; + + /** + * Chunksize for encoding. Not used when decoding. + * A value of zero or less implies no chunking of the encoded data. + * Rounded down to nearest multiple of encodedBlockSize. + */ + protected final int lineLength; + + /** + * Size of chunk separator. Not used unless {@link #lineLength} > 0. + */ + private final int chunkSeparatorLength; + + /** + * Note lineLength is rounded down to the nearest multiple of {@link #encodedBlockSize} + * If chunkSeparatorLength is zero, then chunking is disabled. + * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) + * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) + * @param lineLength if > 0, use chunking with a length lineLength + * @param chunkSeparatorLength the chunk separator length, if relevant + */ + protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, + final int lineLength, final int chunkSeparatorLength) { + this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT); + } + + /** + * Note lineLength is rounded down to the nearest multiple of {@link #encodedBlockSize} + * If chunkSeparatorLength is zero, then chunking is disabled. + * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) + * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) + * @param lineLength if > 0, use chunking with a length lineLength + * @param chunkSeparatorLength the chunk separator length, if relevant + * @param pad byte used as padding byte. + */ + protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, + final int lineLength, final int chunkSeparatorLength, final byte pad) { + this.unencodedBlockSize = unencodedBlockSize; + this.encodedBlockSize = encodedBlockSize; + final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0; + this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0; + this.chunkSeparatorLength = chunkSeparatorLength; + + this.pad = pad; + } + + /** + * Returns true if this object has buffered data for reading. + * + * @param context the context to be used + * @return true if there is data still available for reading. + */ + boolean hasData(final Context context) { // package protected for access from I/O streams + return context.buffer != null; + } + + /** + * Returns the amount of buffered data available for reading. + * + * @param context the context to be used + * @return The amount of buffered data available for reading. + */ + int available(final Context context) { // package protected for access from I/O streams + return context.buffer != null ? context.pos - context.readPos : 0; + } + + /** + * Get the default buffer size. Can be overridden. + * + * @return {@link #DEFAULT_BUFFER_SIZE} + */ + protected int getDefaultBufferSize() { + return DEFAULT_BUFFER_SIZE; + } + + /** + * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. + * @param context the context to be used + */ + private byte[] resizeBuffer(final Context context) { + if (context.buffer == null) { + context.buffer = new byte[getDefaultBufferSize()]; + context.pos = 0; + context.readPos = 0; + } else { + final byte[] b = new byte[context.buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR]; + System.arraycopy(context.buffer, 0, b, 0, context.buffer.length); + context.buffer = b; + } + return context.buffer; + } + + /** + * Ensure that the buffer has room for size bytes + * + * @param size minimum spare space required + * @param context the context to be used + * @return the buffer + */ + protected byte[] ensureBufferSize(final int size, final Context context){ + if ((context.buffer == null) || (context.buffer.length < context.pos + size)){ + return resizeBuffer(context); + } + return context.buffer; + } + + /** + * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail + * bytes. Returns how many bytes were actually extracted. + *

+ * Package protected for access from I/O streams. + * + * @param b + * byte[] array to extract the buffered data into. + * @param bPos + * position in byte[] array to start extraction at. + * @param bAvail + * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available). + * @param context + * the context to be used + * @return The number of bytes successfully extracted into the provided byte[] array. + */ + int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) { + if (context.buffer != null) { + final int len = Math.min(available(context), bAvail); + System.arraycopy(context.buffer, context.readPos, b, bPos, len); + context.readPos += len; + if (context.readPos >= context.pos) { + context.buffer = null; // so hasData() will return false, and this method can return -1 + } + return len; + } + return context.eof ? EOF : 0; + } + + /** + * Checks if a byte value is whitespace or not. + * Whitespace is taken to mean: space, tab, CR, LF + * @param byteToCheck + * the byte to check + * @return true if byte is whitespace, false otherwise + */ + protected static boolean isWhiteSpace(final byte byteToCheck) { + switch (byteToCheck) { + case ' ' : + case '\n' : + case '\r' : + case '\t' : + return true; + default : + return false; + } + } + + /** + * Encodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of + * the Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[]. + * + * @param obj + * Object to encode + * @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied. + * @throws EncoderException + * if the parameter supplied is not of type byte[] + */ + @Override + public Object encode(final Object obj) throws EncoderException { + if (!(obj instanceof byte[])) { + throw new EncoderException("Parameter supplied to Base-N encode is not a byte[]"); + } + return encode((byte[]) obj); + } + + /** + * Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet. + * Uses UTF8 encoding. + * + * @param pArray + * a byte array containing binary data + * @return A String containing only Base-N character data + */ + public String encodeToString(final byte[] pArray) { + return StringUtils.newStringUtf8(encode(pArray)); + } + + /** + * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet. + * Uses UTF8 encoding. + * + * @param pArray a byte array containing binary data + * @return String containing only character data in the appropriate alphabet. + * @since 1.5 + * This is a duplicate of {@link #encodeToString(byte[])}; it was merged during refactoring. + */ + public String encodeAsString(final byte[] pArray){ + return StringUtils.newStringUtf8(encode(pArray)); + } + + /** + * Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of + * the Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String. + * + * @param obj + * Object to decode + * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String + * supplied. + * @throws DecoderException + * if the parameter supplied is not of type byte[] + */ + @Override + public Object decode(final Object obj) throws DecoderException { + if (obj instanceof byte[]) { + return decode((byte[]) obj); + } else if (obj instanceof String) { + return decode((String) obj); + } else { + throw new DecoderException("Parameter supplied to Base-N decode is not a byte[] or a String"); + } + } + + /** + * Decodes a String containing characters in the Base-N alphabet. + * + * @param pArray + * A String containing Base-N character data + * @return a byte array containing binary data + */ + public byte[] decode(final String pArray) { + return decode(StringUtils.getBytesUtf8(pArray)); + } + + /** + * Decodes a byte[] containing characters in the Base-N alphabet. + * + * @param pArray + * A byte array containing Base-N character data + * @return a byte array containing binary data + */ + @Override + public byte[] decode(final byte[] pArray) { + if (pArray == null || pArray.length == 0) { + return pArray; + } + final Context context = new Context(); + decode(pArray, 0, pArray.length, context); + decode(pArray, 0, EOF, context); // Notify decoder of EOF. + final byte[] result = new byte[context.pos]; + readResults(result, 0, result.length, context); + return result; + } + + /** + * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet. + * + * @param pArray + * a byte array containing binary data + * @return A byte array containing only the base N alphabetic character data + */ + @Override + public byte[] encode(final byte[] pArray) { + if (pArray == null || pArray.length == 0) { + return pArray; + } + return encode(pArray, 0, pArray.length); + } + + /** + * Encodes a byte[] containing binary data, into a byte[] containing + * characters in the alphabet. + * + * @param pArray + * a byte array containing binary data + * @param offset + * initial offset of the subarray. + * @param length + * length of the subarray. + * @return A byte array containing only the base N alphabetic character data + * @since 1.11 + */ + public byte[] encode(final byte[] pArray, final int offset, final int length) { + if (pArray == null || pArray.length == 0) { + return pArray; + } + final Context context = new Context(); + encode(pArray, offset, length, context); + encode(pArray, offset, EOF, context); // Notify encoder of EOF. + final byte[] buf = new byte[context.pos - context.readPos]; + readResults(buf, 0, buf.length, context); + return buf; + } + + // package protected for access from I/O streams + abstract void encode(byte[] pArray, int i, int length, Context context); + + // package protected for access from I/O streams + abstract void decode(byte[] pArray, int i, int length, Context context); + + /** + * Returns whether or not the octet is in the current alphabet. + * Does not allow whitespace or pad. + * + * @param value The value to test + * + * @return true if the value is defined in the current alphabet, false otherwise. + */ + protected abstract boolean isInAlphabet(byte value); + + /** + * Tests a given byte array to see if it contains only valid characters within the alphabet. + * The method optionally treats whitespace and pad as valid. + * + * @param arrayOctet byte array to test + * @param allowWSPad if true, then whitespace and PAD are also allowed + * + * @return true if all bytes are valid characters in the alphabet or if the byte array is empty; + * false, otherwise + */ + public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) { + for (final byte octet : arrayOctet) { + if (!isInAlphabet(octet) && + (!allowWSPad || (octet != pad) && !isWhiteSpace(octet))) { + return false; + } + } + return true; + } + + /** + * Tests a given String to see if it contains only valid characters within the alphabet. + * The method treats whitespace and PAD as valid. + * + * @param basen String to test + * @return true if all characters in the String are valid characters in the alphabet or if + * the String is empty; false, otherwise + * @see #isInAlphabet(byte[], boolean) + */ + public boolean isInAlphabet(final String basen) { + return isInAlphabet(StringUtils.getBytesUtf8(basen), true); + } + + /** + * Tests a given byte array to see if it contains any characters within the alphabet or PAD. + * + * Intended for use in checking line-ending arrays + * + * @param arrayOctet + * byte array to test + * @return true if any byte is a valid character in the alphabet or PAD; false otherwise + */ + protected boolean containsAlphabetOrPad(final byte[] arrayOctet) { + if (arrayOctet == null) { + return false; + } + for (final byte element : arrayOctet) { + if (pad == element || isInAlphabet(element)) { + return true; + } + } + return false; + } + + /** + * Calculates the amount of space needed to encode the supplied array. + * + * @param pArray byte[] array which will later be encoded + * + * @return amount of space needed to encoded the supplied array. + * Returns a long since a max-len array will require > Integer.MAX_VALUE + */ + public long getEncodedLength(final byte[] pArray) { + // Calculate non-chunked size - rounded up to allow for padding + // cast to long is needed to avoid possibility of overflow + long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize; + if (lineLength > 0) { // We're using chunking + // Round up to nearest multiple + len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength; + } + return len; + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/BinaryDecoder.java b/src/main/java/com/webank/weid/util/Multibase/BinaryDecoder.java new file mode 100644 index 00000000..3e3e4a8a --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/BinaryDecoder.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Defines common decoding methods for byte array decoders. + * + * @version $Id$ + */ +public interface BinaryDecoder extends Decoder { + + /** + * Decodes a byte array and returns the results as a byte array. + * + * @param source + * A byte array which has been encoded with the appropriate encoder + * @return a byte array that contains decoded content + * @throws DecoderException + * A decoder exception is thrown if a Decoder encounters a failure condition during the decode process. + */ + byte[] decode(byte[] source) throws DecoderException; +} + diff --git a/src/main/java/com/webank/weid/util/Multibase/BinaryEncoder.java b/src/main/java/com/webank/weid/util/Multibase/BinaryEncoder.java new file mode 100644 index 00000000..3314bf2b --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/BinaryEncoder.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Defines common encoding methods for byte array encoders. + * + * @version $Id$ + */ +public interface BinaryEncoder extends Encoder { + + /** + * Encodes a byte array and return the encoded data as a byte array. + * + * @param source + * Data to be encoded + * @return A byte array containing the encoded data + * @throws EncoderException + * thrown if the Encoder encounters a failure condition during the encoding process. + */ + byte[] encode(byte[] source) throws EncoderException; +} + diff --git a/src/main/java/com/webank/weid/util/Multibase/CharEncoding.java b/src/main/java/com/webank/weid/util/Multibase/CharEncoding.java new file mode 100644 index 00000000..563d640c --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/CharEncoding.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Character encoding names required of every implementation of the Java platform. + * + * From the Java documentation Standard charsets: + *

+ * Every implementation of the Java platform is required to support the following character encodings. Consult the + * release documentation for your implementation to see if any other encodings are supported. Consult the release + * documentation for your implementation to see if any other encodings are supported. + *

+ * + *
    + *
  • US-ASCII
    + * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.
  • + *
  • ISO-8859-1
    + * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
  • + *
  • UTF-8
    + * Eight-bit Unicode Transformation Format.
  • + *
  • UTF-16BE
    + * Sixteen-bit Unicode Transformation Format, big-endian byte order.
  • + *
  • UTF-16LE
    + * Sixteen-bit Unicode Transformation Format, little-endian byte order.
  • + *
  • UTF-16
    + * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order + * accepted on input, big-endian used on output.)
  • + *
+ * + * This perhaps would best belong in the [lang] project. Even if a similar interface is defined in [lang], it is not + * foreseen that [codec] would be made to depend on [lang]. + * + *

+ * This class is immutable and thread-safe. + *

+ * + * @see Standard charsets + * @since 1.4 + * @version $Id$ + */ +public class CharEncoding { + /** + * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1. + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String ISO_8859_1 = "ISO-8859-1"; + + /** + * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set. + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String US_ASCII = "US-ASCII"; + + /** + * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark + * (either order accepted on input, big-endian used on output) + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String UTF_16 = "UTF-16"; + + /** + * Sixteen-bit Unicode Transformation Format, big-endian byte order. + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String UTF_16BE = "UTF-16BE"; + + /** + * Sixteen-bit Unicode Transformation Format, little-endian byte order. + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String UTF_16LE = "UTF-16LE"; + + /** + * Eight-bit Unicode Transformation Format. + *

+ * Every implementation of the Java platform is required to support this character encoding. + * + * @see Standard charsets + */ + public static final String UTF_8 = "UTF-8"; +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Charsets.java b/src/main/java/com/webank/weid/util/Multibase/Charsets.java new file mode 100644 index 00000000..a3f71a2b --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Charsets.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.util.Multibase; + +import java.nio.charset.Charset; + +/** + * Charsets required of every implementation of the Java platform. + * + * From the Java documentation Standard + * charsets: + *

+ * Every implementation of the Java platform is required to support the following character encodings. Consult the + * release documentation for your implementation to see if any other encodings are supported. Consult the release + * documentation for your implementation to see if any other encodings are supported. + *

+ * + *
    + *
  • US-ASCII
    + * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.
  • + *
  • ISO-8859-1
    + * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
  • + *
  • UTF-8
    + * Eight-bit Unicode Transformation Format.
  • + *
  • UTF-16BE
    + * Sixteen-bit Unicode Transformation Format, big-endian byte order.
  • + *
  • UTF-16LE
    + * Sixteen-bit Unicode Transformation Format, little-endian byte order.
  • + *
  • UTF-16
    + * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order + * accepted on input, big-endian used on output.)
  • + *
+ * + * This perhaps would best belong in the Commons Lang project. Even if a similar class is defined in Commons Lang, it is + * not foreseen that Commons Codec would be made to depend on Commons Lang. + * + *

+ * This class is immutable and thread-safe. + *

+ * + * @see Standard charsets + * @since 1.7 + * @version $Id: CharEncoding.java 1173287 2011-09-20 18:16:19Z ggregory $ + */ +public class Charsets { + + // + // This class should only contain Charset instances for required encodings. This guarantees that it will load + // correctly and without delay on all Java platforms. + // + + /** + * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set. + *

+ * Every implementation of the Java platform is required to support this character encoding. + *

+ *

+ * On Java 7 or later, use {@link java.nio.charset.StandardCharsets#ISO_8859_1} instead. + *

+ * + * @see Standard charsets + */ + public static final Charset US_ASCII = Charset.forName(CharEncoding.US_ASCII); + + /** + * Eight-bit Unicode Transformation Format. + *

+ * Every implementation of the Java platform is required to support this character encoding. + *

+ *

+ * On Java 7 or later, use {@link java.nio.charset.StandardCharsets#ISO_8859_1} instead. + *

+ * + * @see Standard charsets + */ + public static final Charset UTF_8 = Charset.forName(CharEncoding.UTF_8); +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Decoder.java b/src/main/java/com/webank/weid/util/Multibase/Decoder.java new file mode 100644 index 00000000..ea210dd0 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Decoder.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Provides the highest level of abstraction for Decoders. + *

+ * This is the sister interface of {@link Encoder}. All Decoders implement this common generic interface. + * Allows a user to pass a generic Object to any Decoder implementation in the codec package. + *

+ * One of the two interfaces at the center of the codec package. + * + * @version $Id$ + */ +public interface Decoder { + + /** + * Decodes an "encoded" Object and returns a "decoded" Object. Note that the implementation of this interface will + * try to cast the Object parameter to the specific type expected by a particular Decoder implementation. If a + * {@link ClassCastException} occurs this decode method will throw a DecoderException. + * + * @param source + * the object to decode + * @return a 'decoded" object + * @throws DecoderException + * a decoder exception can be thrown for any number of reasons. Some good candidates are that the + * parameter passed to this method is null, a param cannot be cast to the appropriate type for a + * specific encoder. + */ + Object decode(Object source) throws DecoderException; +} + diff --git a/src/main/java/com/webank/weid/util/Multibase/DecoderException.java b/src/main/java/com/webank/weid/util/Multibase/DecoderException.java new file mode 100644 index 00000000..8694afc1 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/DecoderException.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Thrown when there is a failure condition during the decoding process. This exception is thrown when a {@link Decoder} + * encounters a decoding specific exception such as invalid data, or characters outside of the expected range. + * + * @version $Id$ + */ +public class DecoderException extends Exception { + + /** + * Declares the Serial Version Uid. + * + * @see Always Declare Serial Version Uid + */ + private static final long serialVersionUID = 1L; + + /** + * Constructs a new exception with null as its detail message. The cause is not initialized, and may + * subsequently be initialized by a call to {@link #initCause}. + * + * @since 1.4 + */ + public DecoderException() { + super(); + } + + /** + * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently + * be initialized by a call to {@link #initCause}. + * + * @param message + * The detail message which is saved for later retrieval by the {@link #getMessage()} method. + */ + public DecoderException(final String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + *

+ * Note that the detail message associated with cause is not automatically incorporated into this + * exception's detail message. + * + * @param message + * The detail message which is saved for later retrieval by the {@link #getMessage()} method. + * @param cause + * The cause which is saved for later retrieval by the {@link #getCause()} method. A null + * value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 1.4 + */ + public DecoderException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail message of (cause==null ? + * null : cause.toString()) (which typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than wrappers for other throwables. + * + * @param cause + * The cause which is saved for later retrieval by the {@link #getCause()} method. A null + * value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 1.4 + */ + public DecoderException(final Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Encoder.java b/src/main/java/com/webank/weid/util/Multibase/Encoder.java new file mode 100644 index 00000000..2904bec2 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Encoder.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Provides the highest level of abstraction for Encoders. + *

+ * This is the sister interface of {@link Decoder}. Every implementation of Encoder provides this + * common generic interface which allows a user to pass a generic Object to any Encoder implementation + * in the codec package. + * + * @version $Id$ + */ +public interface Encoder { + + /** + * Encodes an "Object" and returns the encoded content as an Object. The Objects here may just be + * byte[] or Strings depending on the implementation used. + * + * @param source + * An object to encode + * @return An "encoded" Object + * @throws EncoderException + * An encoder exception is thrown if the encoder experiences a failure condition during the encoding + * process. + */ + Object encode(Object source) throws EncoderException; +} + diff --git a/src/main/java/com/webank/weid/util/Multibase/EncoderException.java b/src/main/java/com/webank/weid/util/Multibase/EncoderException.java new file mode 100644 index 00000000..97256548 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/EncoderException.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +/** + * Thrown when there is a failure condition during the encoding process. This exception is thrown when an + * {@link Encoder} encounters a encoding specific exception such as invalid data, inability to calculate a checksum, + * characters outside of the expected range. + * + * @version $Id$ + */ +public class EncoderException extends Exception { + + /** + * Declares the Serial Version Uid. + * + * @see Always Declare Serial Version Uid + */ + private static final long serialVersionUID = 1L; + + /** + * Constructs a new exception with null as its detail message. The cause is not initialized, and may + * subsequently be initialized by a call to {@link #initCause}. + * + * @since 1.4 + */ + public EncoderException() { + super(); + } + + /** + * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently + * be initialized by a call to {@link #initCause}. + * + * @param message + * a useful message relating to the encoder specific error. + */ + public EncoderException(final String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + *

+ * Note that the detail message associated with cause is not automatically incorporated into this + * exception's detail message. + *

+ * + * @param message + * The detail message which is saved for later retrieval by the {@link #getMessage()} method. + * @param cause + * The cause which is saved for later retrieval by the {@link #getCause()} method. A null + * value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 1.4 + */ + public EncoderException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail message of (cause==null ? + * null : cause.toString()) (which typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than wrappers for other throwables. + * + * @param cause + * The cause which is saved for later retrieval by the {@link #getCause()} method. A null + * value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 1.4 + */ + public EncoderException(final Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/Multibase.java b/src/main/java/com/webank/weid/util/Multibase/Multibase.java new file mode 100644 index 00000000..a8c083ce --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/Multibase.java @@ -0,0 +1,131 @@ +package com.webank.weid.util.Multibase; + +import java.util.*; + + +public class Multibase { + + public enum Base { + Base1('1'), + Base2('0'), + Base8('7'), + Base10('9'), + Base16('f'), + Base16Upper('F'), + Base32('b'), + Base32Upper('B'), + Base32Pad('c'), + Base32PadUpper('C'), + Base32Hex('v'), + Base32HexUpper('V'), + Base32HexPad('t'), + Base32HexPadUpper('T'), + Base36('k'), + Base36Upper('K'), + Base58BTC('z'), + Base58Flickr('Z'), + Base64('m'), + Base64Url('u'), + Base64Pad('M'), + Base64UrlPad('U'); + + public char prefix; + + Base(char prefix) { + this.prefix = prefix; + } + + private static Map lookup = new TreeMap<>(); + static { + for (Base b: Base.values()) + lookup.put(b.prefix, b); + } + + public static Base lookup(char p) { + if (!lookup.containsKey(p)) + throw new IllegalStateException("Unknown Multibase type: " + p); + return lookup.get(p); + } + } + + public static String encode(Base b, byte[] data) { + switch (b) { + case Base58BTC: + return b.prefix + Base58.encode(data); + case Base16: + return b.prefix + Base16.encode(data); + case Base16Upper: + return b.prefix + Base16.encode(data).toUpperCase(); + case Base32: + return b.prefix + new String(new Base32().encode(data)).toLowerCase().replaceAll("=", ""); + case Base32Pad: + return b.prefix + new String(new Base32().encode(data)).toLowerCase(); + case Base32PadUpper: + return b.prefix + new String(new Base32().encode(data)); + case Base32Upper: + return b.prefix + new String(new Base32().encode(data)).replaceAll("=", ""); + case Base32Hex: + return b.prefix + new String(new Base32(true).encode(data)).toLowerCase().replaceAll("=", ""); + case Base32HexPad: + return b.prefix + new String(new Base32(true).encode(data)).toLowerCase(); + case Base32HexPadUpper: + return b.prefix + new String(new Base32(true).encode(data)); + case Base32HexUpper: + return b.prefix + new String(new Base32(true).encode(data)).replaceAll("=", ""); + case Base36: + return b.prefix + Base36.encode(data); + case Base36Upper: + return b.prefix + Base36.encode(data).toUpperCase(); + case Base64: + return b.prefix + Base64.encodeBase64String(data).replaceAll("=", ""); + case Base64Url: + return b.prefix + Base64.encodeBase64URLSafeString(data).replaceAll("=", ""); + case Base64Pad: + return b.prefix + Base64.encodeBase64String(data); + case Base64UrlPad: + return b.prefix + Base64.encodeBase64String(data).replaceAll("\\+", "-").replaceAll("/", "_"); + default: + throw new IllegalStateException("Unsupported base encoding: " + b.name()); + } + } + + public static Base encoding(String data) { + return Base.lookup(data.charAt(0)); + } + + public static byte[] decode(String data) { + Base b = encoding(data); + String rest = data.substring(1); + switch (b) { + case Base58BTC: + return Base58.decode(rest); + case Base16: + return Base16.decode(rest); + case Base16Upper: + return Base16.decode(rest.toLowerCase()); + case Base32: + case Base32Pad: + return new Base32().decode(rest); + case Base32PadUpper: + case Base32Upper: + return new Base32().decode(rest.toLowerCase()); + case Base32Hex: + case Base32HexPad: + return new Base32(true).decode(rest); + case Base32HexPadUpper: + case Base32HexUpper: + return new Base32(true).decode(rest.toLowerCase()); + case Base36: + return Base36.decode(rest); + case Base36Upper: + return Base36.decode(rest.toLowerCase()); + case Base64: + case Base64Url: + case Base64Pad: + case Base64UrlPad: + return Base64.decodeBase64(rest); + default: + throw new IllegalStateException("Unsupported base encoding: " + b.name()); + } + } +} diff --git a/src/main/java/com/webank/weid/util/Multibase/StringUtils.java b/src/main/java/com/webank/weid/util/Multibase/StringUtils.java new file mode 100644 index 00000000..ac33eab1 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multibase/StringUtils.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.webank.weid.util.Multibase; + +import java.nio.charset.Charset; + +/** + * Converts String to and from bytes using the encodings required by the Java specification. These encodings are + * specified in + * Standard charsets. + * + *

This class is immutable and thread-safe.

+ * + * @see Standard charsets + * @version $Id$ + * @since 1.4 + */ +public class StringUtils { + + /** + * Calls {@link String#getBytes(Charset)} + * + * @param string + * The string to encode (if null, return null). + * @param charset + * The {@link Charset} to encode the String + * @return the encoded bytes + */ + private static byte[] getBytes(final String string, final Charset charset) { + if (string == null) { + return null; + } + return string.getBytes(charset); + } + + /** + * Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte + * array. + * + * @param string + * the String to encode, may be null + * @return encoded bytes, or null if the input string was null + * @throws NullPointerException + * Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is + * required by the Java platform specification. + * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException + * @see Standard charsets + */ + public static byte[] getBytesUtf8(final String string) { + return getBytes(string, Charset.forName("UTF-8")); + } + + /** + * Constructs a new String by decoding the specified array of bytes using the given charset. + * + * @param bytes + * The bytes to be decoded into characters + * @param charset + * The {@link Charset} to encode the String; not {@code null} + * @return A new String decoded from the specified array of bytes using the given charset, + * or null if the input byte array was null. + * @throws NullPointerException + * Thrown if charset is {@code null} + */ + private static String newString(final byte[] bytes, final Charset charset) { + return bytes == null ? null : new String(bytes, charset); + } + + /** + * Constructs a new String by decoding the specified array of bytes using the US-ASCII charset. + * + * @param bytes + * The bytes to be decoded into characters + * @return A new String decoded from the specified array of bytes using the US-ASCII charset, + * or null if the input byte array was null. + * @throws NullPointerException + * Thrown if {@link Charsets#US_ASCII} is not initialized, which should never happen since it is + * required by the Java platform specification. + * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException + */ + public static String newStringUsAscii(final byte[] bytes) { + return newString(bytes, Charset.forName("US-ASCII")); + } + + /** + * Constructs a new String by decoding the specified array of bytes using the UTF-8 charset. + * + * @param bytes + * The bytes to be decoded into characters + * @return A new String decoded from the specified array of bytes using the UTF-8 charset, + * or null if the input byte array was null. + * @throws NullPointerException + * Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is + * required by the Java platform specification. + * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException + */ + public static String newStringUtf8(final byte[] bytes) { + return newString(bytes, Charset.forName("UTF-8")); + } + +} diff --git a/src/main/java/com/webank/weid/util/Multicodec/DecodedData.java b/src/main/java/com/webank/weid/util/Multicodec/DecodedData.java new file mode 100644 index 00000000..97dd9600 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multicodec/DecodedData.java @@ -0,0 +1,67 @@ +package com.webank.weid.util.Multicodec; + +import lombok.Data; + +/** + *

A bean to encapsulate decoded data and its codec.

+ *

The bean provides access to an array of bytes to express the decoded data payload. + * The data can set/get either as a byte[] or as a hex string in such a way as the operations are consistent ways to act + * on the same payload of data.

+ */ +@Data +public class DecodedData { + private Multicodec codec; + private byte[] data; + + public DecodedData() { + } + + /** + * Sets the Multicodec value of the data. + * @param codec the Multicodec value of the data. + */ + public void setCodec(Multicodec codec) { + this.codec = codec; + } + + /** + * Gets the data as a byte array. + * @return the data as a byte array. + */ + public byte[] getDataAsBytes() { + return data; + } + + /** + * Sets the data. + * @param data the data as a byte array. + */ + public void setData(byte[] data) { + this.data = data; + } + + /** + * Alternative method to get the data as a hex string. + * @return get the data as a hex string. + */ + public String getDataAsHex() { + return HexUtils.bytesToHex(this.data); + } + + /** + * Alternative method to set the data as a hex string. + * @param hexData the data as a hex string. + */ + public void setData(String hexData) { + setData(HexUtils.hexToBytes(hexData)); + } + + /** + * Determines if this object is populated with non-null information. + * @return true, if this object is populated with non-null information. + */ + public boolean isSet() { + return (getCodec() != null) && (getDataAsBytes() != null && getDataAsBytes().length > 0); + + } +} diff --git a/src/main/java/com/webank/weid/util/Multicodec/HexUtils.java b/src/main/java/com/webank/weid/util/Multicodec/HexUtils.java new file mode 100644 index 00000000..284087f5 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multicodec/HexUtils.java @@ -0,0 +1,36 @@ +package com.webank.weid.util.Multicodec; + +import org.apache.commons.lang3.StringUtils; + +/** + * Utility to convert between an array of bytes and a string of hexadecimal representations of bytes. + */ +public class HexUtils { + + private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + + public static byte[] hexToBytes(String s) { + + //Strip the '0x' characters at the front of the string if they exist. + s = StringUtils.remove(s, "0x"); + s = s.toUpperCase(); + + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } +} diff --git a/src/main/java/com/webank/weid/util/Multicodec/Multicodec.java b/src/main/java/com/webank/weid/util/Multicodec/Multicodec.java new file mode 100644 index 00000000..d0e53e3a --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multicodec/Multicodec.java @@ -0,0 +1,559 @@ +package com.webank.weid.util.Multicodec; + +import java.util.Map; +import java.util.TreeMap; + +/** + * Refer to: https://github.com/multiformats/multicodec/blob/master/table.csv + */ +public enum Multicodec { + IDENTITY("0x00"), + CIDV1("0x01"), + CIDV2("0x02"), + CIDV3("0x03"), + IP4("0x04"), + TCP("0x06"), + SHA1("0x11"), + SHA2_256("0x12"), + SHA2_512("0x13"), + SHA3_512("0x14"), + SHA3_384("0x15"), + SHA3_256("0x16"), + SHA3_224("0x17"), + SHAKE_128("0x18"), + SHAKE_256("0x19"), + KECCAK_224("0x1A"), + KECCAK_256("0x1B"), + KECCAK_384("0x1C"), + KECCAK_512("0x1D"), + BLAKE3("0x1E"), + SHA2_384("0x20"), + DCCP("0x21"), + MURMUR3_X64_64("0x22"), + MURMUR3_32("0x23"), + IP6("0x29"), + IP6ZONE("0x2A"), + PATH("0x2F"), + MULTICODEC("0x30"), + MULTIHASH("0x31"), + MULTIADDR("0x32"), + MULTIBASE("0x33"), + DNS("0x35"), + DNS4("0x36"), + DNS6("0x37"), + DNSADDR("0x38"), + PROTOBUF("0x50"), + CBOR("0x51"), + RAW("0x55"), + DBL_SHA2_256("0x56"), + RLP("0x60"), + BENCODE("0x63"), + DAG_PB("0x70"), + DAG_CBOR("0x71"), + LIBP2P_KEY("0x72"), + GIT_RAW("0x78"), + TORRENT_INFO("0x7B"), + TORRENT_FILE("0x7C"), + LEOFCOIN_BLOCK("0x81"), + LEOFCOIN_TX("0x82"), + LEOFCOIN_PR("0x83"), + SCTP("0x84"), + DAG_JOSE("0x85"), + DAG_COSE("0x86"), + ETH_BLOCK("0x90"), + ETH_BLOCK_LIST("0x91"), + ETH_TX_TRIE("0x92"), + ETH_TX("0x93"), + ETH_TX_RECEIPT_TRIE("0x94"), + ETH_TX_RECEIPT("0x95"), + ETH_STATE_TRIE("0x96"), + ETH_ACCOUNT_SNAPSHOT("0x97"), + ETH_STORAGE_TRIE("0x98"), + ETH_RECEIPT_LOG_TRIE("0x99"), + ETH_RECIEPT_LOG("0x9A"), + AES_128("0xA0"), + AES_192("0xA1"), + AES_256("0xA2"), + CHACHA_128("0xA3"), + CHACHA_256("0xA4"), + BITCOIN_BLOCK("0xB0"), + BITCOIN_TX("0xB1"), + BITCOIN_WITNESS_COMMITMENT("0xB2"), + ZCASH_BLOCK("0xC0"), + ZCASH_TX("0xC1"), + CAIP_50("0xCA"), + STREAMID("0xCE"), + STELLAR_BLOCK("0xD0"), + STELLAR_TX("0xD1"), + MD4("0xD4"), + MD5("0xD5"), + DECRED_BLOCK("0xE0"), + DECRED_TX("0xE1"), + IPLD_NS("0xE2"), + IPFS_NS("0xE3"), + SWARM_NS("0xE4"), + IPNS_NS("0xE5"), + ZERONET("0xE6"), + SECP256K1_PUB("0xE7"), + DNSLINK("0xE8"), + BLS12_381_G1_PUB("0xEA"), + BLS12_381_G2_PUB("0xEB"), + X25519_PUB("0xEC"), + ED25519_PUB("0xED01"), + BLS12_381_G1G2_PUB("0xEE"), + DASH_BLOCK("0xF0"), + DASH_TX("0xF1"), + SWARM_MANIFEST("0xFA"), + SWARM_FEED("0xFB"), + UDP("0x0111"), + P2P_WEBRTC_STAR("0x0113"), + P2P_WEBRTC_DIRECT("0x0114"), + P2P_STARDUST("0x0115"), + WEBRTC("0x0118"), + P2P_CIRCUIT("0x0122"), + DAG_JSON("0x0129"), + UDT("0x012D"), + UTP("0x012E"), + UNIX("0x0190"), + THREAD("0x0196"), + P2P("0x01A5"), + IPFS("0x01A5"), + HTTPS("0x01BB"), + ONION("0x01BC"), + ONION3("0x01BD"), + GARLIC64("0x01BE"), + GARLIC32("0x01BF"), + TLS("0x01C0"), + NOISE("0x01C6"), + QUIC("0x01CC"), + WEBTRANSPORT("0x01D1"), + CERTHASH("0x01D2"), + WS("0x01DD"), + WSS("0x01DE"), + P2P_WEBSOCKET_STAR("0x01DF"), + HTTP("0x01E0"), + SWHID_1_SNP("0x01F0"), + JSON("0x0200"), + MESSAGEPACK("0x0201"), + CAR("0x0202"), + LIBP2P_PEER_RECORD("0x0301"), + LIBP2P_RELAY_RSVP("0x0302"), + CAR_INDEX_SORTED("0x0400"), + CAR_MULTIHASH_INDEX_SORTED("0x0401"), + TRANSPORT_BITSWAP("0x0900"), + TRANSPORT_GRAPHSYNC_FILECOINV1("0x0910"), + SHA2_256_TRUNC254_PADDED("0x1012"), + SHA2_224("0x1013"), + SHA2_512_224("0x1014"), + SHA2_512_256("0x1015"), + MURMUR3_X64_128("0x1022"), + RIPEMD_128("0x1052"), + RIPEMD_160("0x1053"), + RIPEMD_256("0x1054"), + RIPEMD_320("0x1055"), + X11("0x1100"), + P256_PUB("0x1200"), + P384_PUB("0x1201"), + P521_PUB("0x1202"), + ED448_PUB("0x1203"), + X448_PUB("0x1204"), + RSA_PUB("0x1205"), + SM2_PUB("0x1206"), + ED25519_PRIV("0x1300"), + SECP256K1_PRIV("0x1301"), + X25519_PRIV("0x1302"), + KANGAROOTWELVE("0x1D01"), + SM3_256("0x534D"), + BLAKE2B_8("0xB201"), + BLAKE2B_16("0xB202"), + BLAKE2B_24("0xB203"), + BLAKE2B_32("0xB204"), + BLAKE2B_40("0xB205"), + BLAKE2B_48("0xB206"), + BLAKE2B_56("0xB207"), + BLAKE2B_64("0xB208"), + BLAKE2B_72("0xB209"), + BLAKE2B_80("0xB20A"), + BLAKE2B_88("0xB20B"), + BLAKE2B_96("0xB20C"), + BLAKE2B_104("0xB20D"), + BLAKE2B_112("0xB20E"), + BLAKE2B_120("0xB20F"), + BLAKE2B_128("0xB210"), + BLAKE2B_136("0xB211"), + BLAKE2B_144("0xB212"), + BLAKE2B_152("0xB213"), + BLAKE2B_160("0xB214"), + BLAKE2B_168("0xB215"), + BLAKE2B_176("0xB216"), + BLAKE2B_184("0xB217"), + BLAKE2B_192("0xB218"), + BLAKE2B_200("0xB219"), + BLAKE2B_208("0xB21A"), + BLAKE2B_216("0xB21B"), + BLAKE2B_224("0xB21C"), + BLAKE2B_232("0xB21D"), + BLAKE2B_240("0xB21E"), + BLAKE2B_248("0xB21F"), + BLAKE2B_256("0xB220"), + BLAKE2B_264("0xB221"), + BLAKE2B_272("0xB222"), + BLAKE2B_280("0xB223"), + BLAKE2B_288("0xB224"), + BLAKE2B_296("0xB225"), + BLAKE2B_304("0xB226"), + BLAKE2B_312("0xB227"), + BLAKE2B_320("0xB228"), + BLAKE2B_328("0xB229"), + BLAKE2B_336("0xB22A"), + BLAKE2B_344("0xB22B"), + BLAKE2B_352("0xB22C"), + BLAKE2B_360("0xB22D"), + BLAKE2B_368("0xB22E"), + BLAKE2B_376("0xB22F"), + BLAKE2B_384("0xB230"), + BLAKE2B_392("0xB231"), + BLAKE2B_400("0xB232"), + BLAKE2B_408("0xB233"), + BLAKE2B_416("0xB234"), + BLAKE2B_424("0xB235"), + BLAKE2B_432("0xB236"), + BLAKE2B_440("0xB237"), + BLAKE2B_448("0xB238"), + BLAKE2B_456("0xB239"), + BLAKE2B_464("0xB23A"), + BLAKE2B_472("0xB23B"), + BLAKE2B_480("0xB23C"), + BLAKE2B_488("0xB23D"), + BLAKE2B_496("0xB23E"), + BLAKE2B_504("0xB23F"), + BLAKE2B_512("0xB240"), + BLAKE2S_8("0xB241"), + BLAKE2S_16("0xB242"), + BLAKE2S_24("0xB243"), + BLAKE2S_32("0xB244"), + BLAKE2S_40("0xB245"), + BLAKE2S_48("0xB246"), + BLAKE2S_56("0xB247"), + BLAKE2S_64("0xB248"), + BLAKE2S_72("0xB249"), + BLAKE2S_80("0xB24A"), + BLAKE2S_88("0xB24B"), + BLAKE2S_96("0xB24C"), + BLAKE2S_104("0xB24D"), + BLAKE2S_112("0xB24E"), + BLAKE2S_120("0xB24F"), + BLAKE2S_128("0xB250"), + BLAKE2S_136("0xB251"), + BLAKE2S_144("0xB252"), + BLAKE2S_152("0xB253"), + BLAKE2S_160("0xB254"), + BLAKE2S_168("0xB255"), + BLAKE2S_176("0xB256"), + BLAKE2S_184("0xB257"), + BLAKE2S_192("0xB258"), + BLAKE2S_200("0xB259"), + BLAKE2S_208("0xB25A"), + BLAKE2S_216("0xB25B"), + BLAKE2S_224("0xB25C"), + BLAKE2S_232("0xB25D"), + BLAKE2S_240("0xB25E"), + BLAKE2S_248("0xB25F"), + BLAKE2S_256("0xB260"), + SKEIN256_8("0xB301"), + SKEIN256_16("0xB302"), + SKEIN256_24("0xB303"), + SKEIN256_32("0xB304"), + SKEIN256_40("0xB305"), + SKEIN256_48("0xB306"), + SKEIN256_56("0xB307"), + SKEIN256_64("0xB308"), + SKEIN256_72("0xB309"), + SKEIN256_80("0xB30A"), + SKEIN256_88("0xB30B"), + SKEIN256_96("0xB30C"), + SKEIN256_104("0xB30D"), + SKEIN256_112("0xB30E"), + SKEIN256_120("0xB30F"), + SKEIN256_128("0xB310"), + SKEIN256_136("0xB311"), + SKEIN256_144("0xB312"), + SKEIN256_152("0xB313"), + SKEIN256_160("0xB314"), + SKEIN256_168("0xB315"), + SKEIN256_176("0xB316"), + SKEIN256_184("0xB317"), + SKEIN256_192("0xB318"), + SKEIN256_200("0xB319"), + SKEIN256_208("0xB31A"), + SKEIN256_216("0xB31B"), + SKEIN256_224("0xB31C"), + SKEIN256_232("0xB31D"), + SKEIN256_240("0xB31E"), + SKEIN256_248("0xB31F"), + SKEIN256_256("0xB320"), + SKEIN512_8("0xB321"), + SKEIN512_16("0xB322"), + SKEIN512_24("0xB323"), + SKEIN512_32("0xB324"), + SKEIN512_40("0xB325"), + SKEIN512_48("0xB326"), + SKEIN512_56("0xB327"), + SKEIN512_64("0xB328"), + SKEIN512_72("0xB329"), + SKEIN512_80("0xB32A"), + SKEIN512_88("0xB32B"), + SKEIN512_96("0xB32C"), + SKEIN512_104("0xB32D"), + SKEIN512_112("0xB32E"), + SKEIN512_120("0xB32F"), + SKEIN512_128("0xB330"), + SKEIN512_136("0xB331"), + SKEIN512_144("0xB332"), + SKEIN512_152("0xB333"), + SKEIN512_160("0xB334"), + SKEIN512_168("0xB335"), + SKEIN512_176("0xB336"), + SKEIN512_184("0xB337"), + SKEIN512_192("0xB338"), + SKEIN512_200("0xB339"), + SKEIN512_208("0xB33A"), + SKEIN512_216("0xB33B"), + SKEIN512_224("0xB33C"), + SKEIN512_232("0xB33D"), + SKEIN512_240("0xB33E"), + SKEIN512_248("0xB33F"), + SKEIN512_256("0xB340"), + SKEIN512_264("0xB341"), + SKEIN512_272("0xB342"), + SKEIN512_280("0xB343"), + SKEIN512_288("0xB344"), + SKEIN512_296("0xB345"), + SKEIN512_304("0xB346"), + SKEIN512_312("0xB347"), + SKEIN512_320("0xB348"), + SKEIN512_328("0xB349"), + SKEIN512_336("0xB34A"), + SKEIN512_344("0xB34B"), + SKEIN512_352("0xB34C"), + SKEIN512_360("0xB34D"), + SKEIN512_368("0xB34E"), + SKEIN512_376("0xB34F"), + SKEIN512_384("0xB350"), + SKEIN512_392("0xB351"), + SKEIN512_400("0xB352"), + SKEIN512_408("0xB353"), + SKEIN512_416("0xB354"), + SKEIN512_424("0xB355"), + SKEIN512_432("0xB356"), + SKEIN512_440("0xB357"), + SKEIN512_448("0xB358"), + SKEIN512_456("0xB359"), + SKEIN512_464("0xB35A"), + SKEIN512_472("0xB35B"), + SKEIN512_480("0xB35C"), + SKEIN512_488("0xB35D"), + SKEIN512_496("0xB35E"), + SKEIN512_504("0xB35F"), + SKEIN512_512("0xB360"), + SKEIN1024_8("0xB361"), + SKEIN1024_16("0xB362"), + SKEIN1024_24("0xB363"), + SKEIN1024_32("0xB364"), + SKEIN1024_40("0xB365"), + SKEIN1024_48("0xB366"), + SKEIN1024_56("0xB367"), + SKEIN1024_64("0xB368"), + SKEIN1024_72("0xB369"), + SKEIN1024_80("0xB36A"), + SKEIN1024_88("0xB36B"), + SKEIN1024_96("0xB36C"), + SKEIN1024_104("0xB36D"), + SKEIN1024_112("0xB36E"), + SKEIN1024_120("0xB36F"), + SKEIN1024_128("0xB370"), + SKEIN1024_136("0xB371"), + SKEIN1024_144("0xB372"), + SKEIN1024_152("0xB373"), + SKEIN1024_160("0xB374"), + SKEIN1024_168("0xB375"), + SKEIN1024_176("0xB376"), + SKEIN1024_184("0xB377"), + SKEIN1024_192("0xB378"), + SKEIN1024_200("0xB379"), + SKEIN1024_208("0xB37A"), + SKEIN1024_216("0xB37B"), + SKEIN1024_224("0xB37C"), + SKEIN1024_232("0xB37D"), + SKEIN1024_240("0xB37E"), + SKEIN1024_248("0xB37F"), + SKEIN1024_256("0xB380"), + SKEIN1024_264("0xB381"), + SKEIN1024_272("0xB382"), + SKEIN1024_280("0xB383"), + SKEIN1024_288("0xB384"), + SKEIN1024_296("0xB385"), + SKEIN1024_304("0xB386"), + SKEIN1024_312("0xB387"), + SKEIN1024_320("0xB388"), + SKEIN1024_328("0xB389"), + SKEIN1024_336("0xB38A"), + SKEIN1024_344("0xB38B"), + SKEIN1024_352("0xB38C"), + SKEIN1024_360("0xB38D"), + SKEIN1024_368("0xB38E"), + SKEIN1024_376("0xB38F"), + SKEIN1024_384("0xB390"), + SKEIN1024_392("0xB391"), + SKEIN1024_400("0xB392"), + SKEIN1024_408("0xB393"), + SKEIN1024_416("0xB394"), + SKEIN1024_424("0xB395"), + SKEIN1024_432("0xB396"), + SKEIN1024_440("0xB397"), + SKEIN1024_448("0xB398"), + SKEIN1024_456("0xB399"), + SKEIN1024_464("0xB39A"), + SKEIN1024_472("0xB39B"), + SKEIN1024_480("0xB39C"), + SKEIN1024_488("0xB39D"), + SKEIN1024_496("0xB39E"), + SKEIN1024_504("0xB39F"), + SKEIN1024_512("0xB3A0"), + SKEIN1024_520("0xB3A1"), + SKEIN1024_528("0xB3A2"), + SKEIN1024_536("0xB3A3"), + SKEIN1024_544("0xB3A4"), + SKEIN1024_552("0xB3A5"), + SKEIN1024_560("0xB3A6"), + SKEIN1024_568("0xB3A7"), + SKEIN1024_576("0xB3A8"), + SKEIN1024_584("0xB3A9"), + SKEIN1024_592("0xB3AA"), + SKEIN1024_600("0xB3AB"), + SKEIN1024_608("0xB3AC"), + SKEIN1024_616("0xB3AD"), + SKEIN1024_624("0xB3AE"), + SKEIN1024_632("0xB3AF"), + SKEIN1024_640("0xB3B0"), + SKEIN1024_648("0xB3B1"), + SKEIN1024_656("0xB3B2"), + SKEIN1024_664("0xB3B3"), + SKEIN1024_672("0xB3B4"), + SKEIN1024_680("0xB3B5"), + SKEIN1024_688("0xB3B6"), + SKEIN1024_696("0xB3B7"), + SKEIN1024_704("0xB3B8"), + SKEIN1024_712("0xB3B9"), + SKEIN1024_720("0xB3BA"), + SKEIN1024_728("0xB3BB"), + SKEIN1024_736("0xB3BC"), + SKEIN1024_744("0xB3BD"), + SKEIN1024_752("0xB3BE"), + SKEIN1024_760("0xB3BF"), + SKEIN1024_768("0xB3C0"), + SKEIN1024_776("0xB3C1"), + SKEIN1024_784("0xB3C2"), + SKEIN1024_792("0xB3C3"), + SKEIN1024_800("0xB3C4"), + SKEIN1024_808("0xB3C5"), + SKEIN1024_816("0xB3C6"), + SKEIN1024_824("0xB3C7"), + SKEIN1024_832("0xB3C8"), + SKEIN1024_840("0xB3C9"), + SKEIN1024_848("0xB3CA"), + SKEIN1024_856("0xB3CB"), + SKEIN1024_864("0xB3CC"), + SKEIN1024_872("0xB3CD"), + SKEIN1024_880("0xB3CE"), + SKEIN1024_888("0xB3CF"), + SKEIN1024_896("0xB3D0"), + SKEIN1024_904("0xB3D1"), + SKEIN1024_912("0xB3D2"), + SKEIN1024_920("0xB3D3"), + SKEIN1024_928("0xB3D4"), + SKEIN1024_936("0xB3D5"), + SKEIN1024_944("0xB3D6"), + SKEIN1024_952("0xB3D7"), + SKEIN1024_960("0xB3D8"), + SKEIN1024_968("0xB3D9"), + SKEIN1024_976("0xB3DA"), + SKEIN1024_984("0xB3DB"), + SKEIN1024_992("0xB3DC"), + SKEIN1024_1000("0xB3DD"), + SKEIN1024_1008("0xB3DE"), + SKEIN1024_1016("0xB3DF"), + SKEIN1024_1024("0xB3E0"), + POSEIDON_BLS12_381_A2_FC1("0xB401"), + POSEIDON_BLS12_381_A2_FC1_SC("0xB402"), + SSZ("0xB501"), + SSZ_SHA2_256_BMT("0xB502"), + ISCC("0xCC01"), + ZEROXCERT_IMPRINT_256("0xCE11"), + FIL_COMMITMENT_UNSEALED("0xF101"), + FIL_COMMITMENT_SEALED("0xF102"), + PLAINTEXTV2("0x706C61"), + HOLOCHAIN_ADR_V0("0x807124"), + HOLOCHAIN_ADR_V1("0x817124"), + HOLOCHAIN_KEY_V0("0x947124"), + HOLOCHAIN_KEY_V1("0x957124"), + HOLOCHAIN_SIG_V0("0xA27124"), + HOLOCHAIN_SIG_V1("0xA37124"), + SKYNET_NS("0xB19910"), + ARWEAVE_NS("0xB29910"), + SUBSPACE_NS("0xB39910"), + KUMANDRA_NS("0xB49910"); + + /** + * The codec code value. + */ + public final String code; + + /** + * The unsigned varint encoding of the code. + */ + public final String uvarintcode; + + Multicodec(String code) { + this.code = code; + this.uvarintcode = uvarint(); + } + + private static final Map codeLookup = new TreeMap<>(); + + static { + for (Multicodec codec : Multicodec.values()) { + codeLookup.put(codec.code, codec); + } + } + + /** + * Performs a lookup on the Codec based on the code value. + * + * @param lookupCode The string code to lookup. + * @return The Codec based on the code value + * @throws IllegalArgumentException if the codec name does not exist. + */ + public static Multicodec lookupByCode(String lookupCode) { + if (!codeLookup.containsKey(lookupCode)) { + throw new IllegalArgumentException("Unknown Multicodec name: " + lookupCode); + } + return codeLookup.get(lookupCode); + } + + /** + * Returns the unsigned varint encoding of the code. + * + * @return the unsigned varint encoding of the code. + */ + private String uvarint() { + byte[] codecBytes = HexUtils.hexToBytes(this.code); + StringBuilder uvarintBuilder = new StringBuilder(); + for (byte codecByte : codecBytes) { + byte[] varInt = VarInt.writeUnsignedVarInt(Byte.toUnsignedInt(codecByte)); + String varIntHex = HexUtils.bytesToHex(varInt); + uvarintBuilder.append(varIntHex); + } + return uvarintBuilder.toString(); + } +} diff --git a/src/main/java/com/webank/weid/util/Multicodec/MulticodecEncoder.java b/src/main/java/com/webank/weid/util/Multicodec/MulticodecEncoder.java new file mode 100644 index 00000000..983cdf06 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multicodec/MulticodecEncoder.java @@ -0,0 +1,96 @@ +package com.webank.weid.util.Multicodec; + +import org.apache.commons.lang3.StringUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Multicodec is part of the Multiformats collection of protocols. + * + * Multiformats is a collection of protocols which aim to future-proof systems, today. They do this mainly by allowing + * data to be self-describable. + * See: https://github.com/multiformats/multiformats + * The Multicodec is an agreed way for encoding bytes with a prefix that specifies the type of encoding. + * The format is therefore a portable and self describing way of expressing an encoding of bytes that does not assume + * a specific context. + * See: https://github.com/multiformats/multicodec + * For example, the multicodec specification is used in the specifications for Decentralised Identifiers (DIDs) in + * regard to the DID Method 'key' specification. + * Therefore, any work on `did:key` implementations needs to also solve for the use of multicodecs. + * See: https://w3c-ccg.github.io/did-method-key + * + */ +public class MulticodecEncoder { + + /** + * Encodes the byte array of data for the multicodec type. + * The multicodec type bytes are unsigned varint encoded and are pre-pended to the byte array. + * @param multicodec The Multicodec enum to encode with. + * @param data The bytes of data to encode. + * @return The multicodec encoding of the input bytes + * + */ + public static byte[] encode(Multicodec multicodec, byte[] data) { + + //Get the multicodec prefix of the encoding type as an array as some codes use multibyte prefixes. + byte[] multicodecBytes = HexUtils.hexToBytes(multicodec.code); + + //Create a byte array pre-pended with the multicodec prefix for the multicodecType + //Taking care that the multicodec prefix must be unsigned varint encoded... + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + + //As per multicodec spec, perform unsigned varint encoding of each byte of the multicodec prefix + for (byte b : multicodecBytes) { + byteArrayOutputStream.write(VarInt.writeUnsignedVarInt(Byte.toUnsignedInt(b))); + } + + //Append the data bytes + byteArrayOutputStream.write(data); + return byteArrayOutputStream.toByteArray(); + + } catch (IOException exIO) { + System.err.println("Unexpected error on multicodec encode: " + exIO.getMessage()); + return null; + } + } + + /** + * Decodes a multicodec encoded byte array. + * Assumption: The decoding only supports single byte codec codes. + * Some codec codes are multibyte values and these cannot be distinguished from single byte codec codes + * when the data follows. + * Consider this encoding of sample data 'A1E9D3D8EC' + * 1. cidv1 encoding starts with 0x10. + * - therefore sample encoding hex data is: 01A1E9D3D8EC + * 2. udp encoding starts with 0x0111 + * - therefore sample encoding hex data is: 0111A1E9D3D8EC + * + * Looking 2 it is impossible to determine if its + * cidv1 encoding with data '11A1E9D3D8EC', + * or if it is udp encoding with data 'A1E9D3D8EC'. + * This suggests an issue in the multi codec specification for codec prefixes greater than 1 byte. + * They cannot be 1:1 unambiguously mapped between each other. + * @param multicodecEncodedData The multicodec encoded data + * @return The DecodedData object + */ + public static DecodedData decode(byte[] multicodecEncodedData) { + + DecodedData data = new DecodedData(); + //No clever shortcuts - we simply loop over the set of the codecs and find a match at the start of the string. + //Remembering that the codec at the start will be unsigned varint encoded ... + String multicodecEncodedDataHex = HexUtils.bytesToHex(multicodecEncodedData); + + for (Multicodec c : Multicodec.values()) { + //as per stated assumption... + int codeLength = HexUtils.hexToBytes(c.code).length; + if ((codeLength == 2) && (multicodecEncodedDataHex.startsWith(c.uvarintcode))) { + data.setCodec(c); + data.setData(StringUtils.removeStart(multicodecEncodedDataHex, c.uvarintcode)); + break; + } + } + return data; + } + +} diff --git a/src/main/java/com/webank/weid/util/Multicodec/VarInt.java b/src/main/java/com/webank/weid/util/Multicodec/VarInt.java new file mode 100644 index 00000000..68ac2de7 --- /dev/null +++ b/src/main/java/com/webank/weid/util/Multicodec/VarInt.java @@ -0,0 +1,189 @@ +package com.webank.weid.util.Multicodec; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * -------------------------------------------------------------------------------- + * + * Encodes signed and unsigned values using a common variable-length + * scheme, found for example in + * http://code.google.com/apis/protocolbuffers/docs/encoding.html + * Google's Protocol Buffers. It uses fewer bytes to encode smaller values, + * but will use slightly more bytes to encode large values. + * Signed values are further encoded using so-called zig-zag encoding + * in order to make them "compatible" with variable-length encoding. + */ + +@SuppressWarnings("GrazieInspection") +public final class VarInt { + + private VarInt() {} + + /** + * Encodes a value using the variable-length encoding from + * http://code.google.com/apis/protocolbuffers/docs/encoding.html + * Google Protocol Buffers. It uses zig-zag encoding to efficiently + * encode signed values. If values are known to be non negative, + * writeUnsignedVarLong should be used. + * + * @param value value to encode + * @param out to write bytes to + * @throws IOException if {@link DataOutput} throws {@link IOException} + */ + public static void writeSignedVarLong(long value, DataOutput out) throws IOException { + // Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types + writeUnsignedVarLong((value << 1) ^ (value >> 63), out); + } + + /** + * Encodes a value using the variable-length encoding from + * http://code.google.com/apis/protocolbuffers/docs/encoding.html + * Google Protocol Buffers. Zig-zag is not used, so input must not be negative. + * If values can be negative, use writeSignedVarLong + * instead. This method treats negative input as like a large unsigned value. + * + * @param value value to encode + * @param out to write bytes to + * @throws IOException if {@link DataOutput} throws {@link IOException} + */ + public static void writeUnsignedVarLong(long value, DataOutput out) throws IOException { + while ((value & 0xFFFFFFFFFFFFFF80L) != 0L) { + out.writeByte(((int) value & 0x7F) | 0x80); + value >>>= 7; + } + out.writeByte((int) value & 0x7F); + } + + public static void writeSignedVarInt(int value, DataOutput out) throws IOException { + // Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types + writeUnsignedVarInt((value << 1) ^ (value >> 31), out); + } + + public static void writeUnsignedVarInt(int value, DataOutput out) throws IOException { + while ((value & 0xFFFFFF80) != 0L) { + out.writeByte((value & 0x7F) | 0x80); + value >>>= 7; + } + out.writeByte(value & 0x7F); + } + + public static byte[] writeSignedVarInt(int value) { + // Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types + return writeUnsignedVarInt((value << 1) ^ (value >> 31)); + } + + public static byte[] writeUnsignedVarInt(int value) { + byte[] byteArrayList = new byte[10]; + int i = 0; + while ((value & 0xFFFFFF80) != 0L) { + byteArrayList[i++] = ((byte) ((value & 0x7F) | 0x80)); + value >>>= 7; + } + byteArrayList[i] = ((byte) (value & 0x7F)); + byte[] out = new byte[i + 1]; + for (; i >= 0; i--) { + out[i] = byteArrayList[i]; + } + return out; + } + + public static long readSignedVarLong(DataInput in) throws IOException { + long raw = readUnsignedVarLong(in); + // This undoes the trick in writeSignedVarLong() + long temp = (((raw << 63) >> 63) ^ raw) >> 1; + // This extra step lets us deal with the largest signed values by treating + // negative results from read unsigned methods as like unsigned values + // Must re-flip the top bit if the original read value had it set. + return temp ^ (raw & (1L << 63)); + } + + public static long readUnsignedVarLong(DataInput in) throws IOException { + long value = 0L; + int i = 0; + long b; + while (((b = in.readByte()) & 0x80L) != 0) { + value |= (b & 0x7F) << i; + i += 7; + if (i > 63) { + throw new IllegalArgumentException("Variable length quantity is too long"); + } + } + return value | (b << i); + } + + public static int readSignedVarInt(DataInput in) throws IOException { + int raw = readUnsignedVarInt(in); + // This undoes the trick in writeSignedVarInt() + int temp = (((raw << 31) >> 31) ^ raw) >> 1; + // This extra step lets us deal with the largest signed values by treating + // negative results from read unsigned methods as like unsigned values. + // Must re-flip the top bit if the original read value had it set. + return temp ^ (raw & (1 << 31)); + } + + public static int readUnsignedVarInt(DataInput in) throws IOException { + int value = 0; + int i = 0; + int b; + while (((b = in.readByte()) & 0x80) != 0) { + value |= (b & 0x7F) << i; + i += 7; + if (i > 35) { + throw new IllegalArgumentException("Variable length quantity is too long"); + } + } + return value | (b << i); + } + + public static int readSignedVarInt(byte b) { + return readSignedVarInt(new byte[] {b}); + } + + public static int readSignedVarInt(byte[] bytes) { + int raw = readUnsignedVarInt(bytes); + // This undoes the trick in writeSignedVarInt() + int temp = (((raw << 31) >> 31) ^ raw) >> 1; + // This extra step lets us deal with the largest signed values by treating + // negative results from read unsigned methods as like unsigned values. + // Must re-flip the top bit if the original read value had it set. + return temp ^ (raw & (1 << 31)); + } + + public static int readUnsignedVarInt(byte b) { + return readUnsignedVarInt(new byte[] {b}); + } + + public static int readUnsignedVarInt(byte[] bytes) { + int value = 0; + int i = 0; + byte rb = Byte.MIN_VALUE; + for (byte b : bytes) { + rb = b; + if ((b & 0x80) == 0) { + break; + } + value |= (b & 0x7f) << i; + i += 7; + if (i > 35) { + throw new IllegalArgumentException("Variable length quantity is too long"); + } + } + return value | (rb << i); + } + +} \ No newline at end of file diff --git a/src/main/java/com/webank/weid/util/PropertyUtils.java b/src/main/java/com/webank/weid/util/PropertyUtils.java new file mode 100644 index 00000000..63734019 --- /dev/null +++ b/src/main/java/com/webank/weid/util/PropertyUtils.java @@ -0,0 +1,99 @@ + + +package com.webank.weid.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Properties; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * tools for properties. + * + * @author tonychen 2019年3月21日 + */ +public final class PropertyUtils { + + private static final Logger logger = LoggerFactory.getLogger(PropertyUtils.class); + private static final String WEIDENTITY_PROP_NAME = "weidentity.properties"; + private static final String FISCO_PROP_NAME = "fisco.properties"; + private static Properties prop = new Properties(); + + static { + load(); + } + + /** + * load properties from specific config file. + * + * @param filePath properties config file. + */ + private static void loadProperties(String filePath) throws IOException { + + InputStream in; + in = PropertyUtils.class.getClassLoader().getResourceAsStream(filePath); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + prop.load(br); + br.close(); + in.close(); + } + + /** + * get property value by specific key. + * + * @param key property key + * @return value of the key + */ + public static String getProperty(String key) { + return prop.getProperty(key); + } + + /** + * get property value by specific key. + * + * @param key property keys + * @param defaultValue default value + * @return value of the key + */ + public static String getProperty(String key, String defaultValue) { + return prop.getProperty(key, defaultValue); + } + + /** + * get the all key from Properties. + * + * @return value of the key Set + */ + public static Set getAllPropertyKey() { + return prop.keySet(); + } + + /** + * load the properties. + */ + private static void load() { + + try { + loadProperties(WEIDENTITY_PROP_NAME); + /*if(getProperty("deploy.style").equals("blockchain")){ + loadProperties(FISCO_PROP_NAME); + }*/ + loadProperties(FISCO_PROP_NAME); + } catch (IOException e) { + logger.error("[PropertyUtils] Load weidentity.properties file failed.", e); + } + } + + /** + * reload the properties. + * + */ + public static void reload() { + load(); + } +} diff --git a/src/main/java/com/webank/weid/util/SignatureUtils.java b/src/main/java/com/webank/weid/util/SignatureUtils.java deleted file mode 100644 index e25cdd83..00000000 --- a/src/main/java/com/webank/weid/util/SignatureUtils.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.util; - -import java.math.BigInteger; - -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; -import org.bcos.web3j.crypto.Sign; -import org.bouncycastle.util.encoders.Base64; - -/** - * The Signature related Utils class. Based on ECDSA Asymmetric Encryption + SHA256 Hash Algorithm. - * - *

Two types of Objects are taken care of in this class: 1. Key-pair (pubkey and privkey). 2. - * Signature. This class provides the following functionalities to them above: 1. Creation of - * Key-Pairs and Signatures. 2. Verification of Key-Pairs and Signatures. 3. Serialization and - * De-serializations. This Util class also takes care of: 1. Base64 and Hex encoding styles. It is - * worth noting that we suggest to add encode/decode instead of plain serial/de-serializations. Most - * implementations are re-factors or wrappers based on FISCO-BCOS web3j and Ethereumj. - * - *

Future support of SM2/SM3 is under construction. - * - * @author chaoxinhu 2018.10 - */ -public class SignatureUtils { - - /** - * Generate a new Key-pair. - * - * @return the EC key pair - * @throws Exception the exception - */ - public static ECKeyPair createKeyPair() throws Exception { - return Keys.createEcKeyPair(); - } - - /** - * Sign a message based on the given key-pairs. The message passed in WILL BE HASHED. - * - * @param message the message - * @param keyPair the key pair - * @return SignatureData - * @throws Exception the exception - */ - public static Sign.SignatureData signMessage(String message, ECKeyPair keyPair) - throws Exception { - return Sign.signMessage(HashUtils.sha3(message.getBytes()), keyPair); - } - - /** - * Sign a message based on the given privateKey in Decimal String BigInt. The message passed in - * WILL BE HASHED. - * - * @param message the message - * @param privateKeyString the private key string - * @return SignatureData - * @throws Exception the exception - */ - public static Sign.SignatureData signMessage(String message, String privateKeyString) - throws Exception { - BigInteger privateKey = new BigInteger(privateKeyString); - ECKeyPair keyPair = new ECKeyPair(privateKey, publicKeyFromPrivate(privateKey)); - return Sign.signMessage(HashUtils.sha3(message.getBytes()), keyPair); - } - - /** - * Extract the Public Key from the message and the SignatureData. - * - * @param message the message - * @param signatureData the signature data - * @return publicKey - * @throws Exception the exception - */ - public static BigInteger signatureToPublicKey(String message, Sign.SignatureData signatureData) - throws Exception { - return Sign.signedMessageToKey(HashUtils.sha3(message.getBytes()), signatureData); - } - - /** - * Verify whether the message and the Signature matches the given public Key. - * - * @param message This should be from the same plain-text source with the signature Data. - * @param signatureData This must be in SignatureData. Caller should call - * simpleSignatureDeserialization. - * @param publicKey This must be in BigInteger. Caller should convert it to BigInt. - * @return true if yes, false otherwise - * @throws Exception the exception - */ - public static boolean verifySignature( - String message, Sign.SignatureData signatureData, BigInteger publicKey) throws Exception { - BigInteger extractedPublicKey = signatureToPublicKey(message, signatureData); - return extractedPublicKey.equals(publicKey); - } - - /** - * Obtain the PublicKey from given PrivateKey. - * - * @param privateKey the private key - * @return publicKey - * @throws Exception the exception - */ - public static BigInteger publicKeyFromPrivate(BigInteger privateKey) throws Exception { - return Sign.publicKeyFromPrivate(privateKey); - } - - /** - * Obtain the WeIdPrivateKey from given PrivateKey. - * - * @param privateKey the private key - * @return WeIdPrivateKey - * @throws Exception the exception - */ - public static ECKeyPair createKeyPairFromPrivate(BigInteger privateKey) throws Exception { - return ECKeyPair.create(privateKey); - } - - /** - * The Base64 encode/decode class. - * - * @param base64Bytes the base 64 bytes - * @return the byte[] - */ - public static byte[] base64Decode(byte[] base64Bytes) { - return Base64.decode(base64Bytes); - } - - /** - * Base 64 encode. - * - * @param nonBase64Bytes the non base 64 bytes - * @return the byte[] - */ - public static byte[] base64Encode(byte[] nonBase64Bytes) { - return Base64.encode(nonBase64Bytes); - } - - /** - * Checks if is valid base 64 string. - * - * @param string the string - * @return true, if is valid base 64 string - */ - public static boolean isValidBase64String(String string) { - return org.apache.commons.codec.binary.Base64.isBase64(string); - } - - /** - * The Serialization/De-serialization class of Key-Pairs. - * - * @param keyPair the key pair - * @return the byte[] - * @throws Exception the exception - */ - public static byte[] simpleKeyPairSerialization(ECKeyPair keyPair) throws Exception { - return Keys.serialize(keyPair); - } - - /** - * Simple key pair deserialization. - * - * @param nonHexedBytes the non hexed bytes - * @return the EC key pair - * @throws Exception the exception - */ - public static ECKeyPair simpleKeyPairDeserialization(byte[] nonHexedBytes) throws Exception { - return Keys.deserialize(nonHexedBytes); - } - - /** - * The Serialization class of Signatures. This is simply a concatenation of bytes of the v, r, - * and s. Ethereum uses a similar approach with a wrapping from Base64. - * https://www.programcreek.com/java-api-examples/index.php?source_dir=redPandaj-master/src/org/redPandaLib/crypt/ECKey.java - * uses a DER-formatted serialization, but it does not entail the v tag, henceforth is more - * complex and computation hungry. - * - * @param signatureData the signature data - * @return the byte[] - */ - public static byte[] simpleSignatureSerialization(Sign.SignatureData signatureData) { - byte[] serializedSignatureData = new byte[65]; - serializedSignatureData[0] = signatureData.getV(); - System.arraycopy(signatureData.getR(), 0, serializedSignatureData, 1, 32); - System.arraycopy(signatureData.getS(), 0, serializedSignatureData, 33, 32); - return serializedSignatureData; - } - - /** - * The De-Serialization class of Signatures. This is simply a de-concatenation of bytes of the - * v, r, and s. - * - * @param serializedSignatureData the serialized signature data - * @return the sign. signature data - */ - public static Sign.SignatureData simpleSignatureDeserialization( - byte[] serializedSignatureData) { - byte v = serializedSignatureData[0]; - byte[] r = new byte[32]; - byte[] s = new byte[32]; - System.arraycopy(serializedSignatureData, 1, r, 0, 32); - System.arraycopy(serializedSignatureData, 33, s, 0, 32); - Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); - return signatureData; - } - - /** - * The De-Serialization class of Signatures accepting raw values of v, r, and s. Note: due to - * the non 1:1 mapping between default encoded Java String and Byte Array, all the parameters - * derived from Byte Array should either be STILL IN Byte Array or Base-64. - * - * @param v the v - * @param r the r - * @param s the s - * @return the sign. signature data - */ - public static Sign.SignatureData rawSignatureDeserialization(int v, byte[] r, byte[] s) { - byte vByte = (byte) v; - return new Sign.SignatureData(vByte, r, s); - } -} diff --git a/src/main/java/com/webank/weid/util/TimestampUtils.java b/src/main/java/com/webank/weid/util/TimestampUtils.java new file mode 100644 index 00000000..455cfd87 --- /dev/null +++ b/src/main/java/com/webank/weid/util/TimestampUtils.java @@ -0,0 +1,425 @@ + + +package com.webank.weid.util; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +import com.google.common.base.Charsets; +import com.google.common.hash.Hashing; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.protocol.request.timestamp.wesign.GetTimestampRequest; +import com.webank.weid.protocol.request.timestamp.wesign.VerifyTimestampRequest; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.protocol.response.timestamp.wesign.AccessTokenResponse; +import com.webank.weid.protocol.response.timestamp.wesign.GetTimestampResponse; +import com.webank.weid.protocol.response.timestamp.wesign.SignTicketResponse; +import com.webank.weid.protocol.response.timestamp.wesign.VerifyTimestampResponse; + +/** + * Util classes for trusted timestamp. + * + * @author chaoxinhu 2019.12 + */ + +public class TimestampUtils { + + private static final Logger logger = LoggerFactory.getLogger(TimestampUtils.class); + + private static String weSignAccessTokenUrl = PropertyUtils.getProperty("wesign.accessTokenUrl"); + private static String weSignTicketUrl = PropertyUtils.getProperty("wesign.signTicketUrl"); + private static String weSignTimestampUrl = PropertyUtils.getProperty("wesign.timestampUrl"); + private static String weSignAppId = PropertyUtils.getProperty("wesign.appId"); + private static String weSignSecret = PropertyUtils.getProperty("wesign.secret"); + private static final String WESIGN_EXTRAVAL_SEPARATOR = ";"; + + public static final String WESIGN_AUTHORITY_NAME = "wesign"; + + /** + * Create a WeSign timestamp bundle for Credential use. Extra values as SIGN and Nonce are + * packed with signature value. + * + * @param hashValue the hash value + * @return the map used for claim + */ + public static ResponseData> createWeSignTimestamp(String hashValue) { + if (StringUtils.isBlank(PropertyUtils.getProperty("wesign.accessTokenUrl"))) { + logger.error("WeSign configuration not ready."); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_UNCONFIGURED); + } + String timestampValue; + Long timestamp; + String extra; + try { + String accessToken = TimestampUtils.getWeSignAccessToken(); + if (StringUtils.isBlank(accessToken)) { + logger.error("Failed to acquire an access token."); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_WESIGN_ERROR); + } + String signTicket = TimestampUtils.getWeSignTicketString(accessToken); + if (StringUtils.isBlank(signTicket)) { + logger.error("Failed to acquire a sign ticket."); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_WESIGN_ERROR); + } + String nonce = TimestampUtils.generateNonce(32, 32).get(0); + String weSignHash = TimestampUtils.getWeSignHash(hashValue); + GetTimestampResponse getResp = TimestampUtils + .getTimestamp(signTicket, nonce, weSignHash); + if (getResp.getCode() != 0) { + logger.error("Failed to acquire a valid timestamp."); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_WESIGN_ERROR); + } + timestampValue = getResp.getResult().getData().getB64TimeStamp(); + String signParam = getWeSignParam(nonce, signTicket); + VerifyTimestampResponse verifyResp = TimestampUtils + .verifyTimestamp(signParam, nonce, weSignHash, timestampValue); + if (verifyResp.getCode() != 0) { + logger.error("Failed to verify a current timestamp."); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_WESIGN_ERROR); + } + timestamp = verifyResp.getResult().getData().getSignTime().getTime(); + extra = WESIGN_EXTRAVAL_SEPARATOR + signParam + WESIGN_EXTRAVAL_SEPARATOR + nonce; + } catch (Exception e) { + logger.error("Error occurred during calling WeSign service: ", e); + return new ResponseData<>(null, ErrorCode.TIMESTAMP_SERVICE_WESIGN_ERROR.getCode(), + e.getMessage()); + } + HashMap map = new HashMap<>(); + map.put("timestampAuthority", WESIGN_AUTHORITY_NAME); + map.put("claimHash", hashValue); + map.put("authoritySignature", timestampValue + extra); + map.put("timestamp", timestamp); + return new ResponseData<>(map, ErrorCode.SUCCESS); + } + + /** + * Verify a WeSign Timestamp value. Extra values as nonce and SIGN must be unmodified. + * + * @param hashValue the hash value + * @param authoritySignature the authoritySignature with nonce and SIGN + * @param timestamp the timestamp value + * @return true if passed the check, false otherwise + */ + public static ResponseData verifyWeSignTimestamp( + String hashValue, + String authoritySignature, + Long timestamp) { + if (StringUtils.isBlank(PropertyUtils.getProperty("wesign.accessTokenUrl"))) { + logger.error("WeSign configuration not ready."); + return new ResponseData<>(false, ErrorCode.TIMESTAMP_SERVICE_UNCONFIGURED); + } + try { + String weSignHash = TimestampUtils.getWeSignHash(hashValue); + String[] values = authoritySignature.split(WESIGN_EXTRAVAL_SEPARATOR); + String timestampValue = values[0]; + String signParam = values[1]; + String nonce = values[2]; + VerifyTimestampResponse verifyResp = TimestampUtils + .verifyTimestamp(signParam, nonce, weSignHash, timestampValue); + if (verifyResp.getCode() != 0) { + return new ResponseData<>(false, ErrorCode.TIMESTAMP_VERIFICATION_FAILED); + } + Long verifiedTimestamp = verifyResp.getResult().getData().getSignTime().getTime(); + if (!verifiedTimestamp.equals(timestamp)) { + return new ResponseData<>(false, ErrorCode.TIMESTAMP_VERIFICATION_FAILED); + } + return new ResponseData<>(true, ErrorCode.SUCCESS); + } catch (Exception e) { + logger.error("Error occurred during processing authority signature: ", e); + return new ResponseData<>(false, ErrorCode.TIMESTAMP_SERVICE_BASE_ERROR); + } + } + + /** + * Get WeSign access token. + * + * @return access token + * @throws Exception any exception + */ + public static String getWeSignAccessToken() throws Exception { + + AccessTokenResponse accessTokenResponse = getWeSignAccessTokenUrl(); + int code = accessTokenResponse.getCode(); + String msg = accessTokenResponse.getMsg(); + if (0 != code) { + logger.error( + "Error occurred during getting access token. code: " + code + ", msg: " + msg); + return null; + } + return accessTokenResponse.getAccess_token(); + } + + private static AccessTokenResponse getWeSignAccessTokenUrl() throws Exception { + return getWeSignAccessTokenUrl( + weSignAccessTokenUrl + + "?app_id={0}&secret={1}&grant_type=client_credential&version=1.0.0", + weSignAppId, + weSignSecret + ); + } + + private static AccessTokenResponse getWeSignAccessTokenUrl(String urlExp, String appId, + String secret) throws Exception { + + logger.info("request arg::urlExp: {}, appId:: {}, secret: {}", urlExp, appId, secret); + if (StringUtils.isBlank(urlExp) || StringUtils.isBlank(appId) || StringUtils + .isBlank(secret)) { + return null; + } + try { + String accessTokenUrl = MessageFormat.format(urlExp, appId, secret); + logger.debug("[getWeSignAccessTokenUrl]:{}", accessTokenUrl); + + String responseData = HttpClient.doGet(accessTokenUrl, true); + logger.debug("[getWeSignAccessTokenUrl]: response: {}", responseData); + + if (null == responseData) { + return null; + } + return DataToolUtils.deserialize(responseData, AccessTokenResponse.class); + } catch (Exception e) { + logger.error("Error occurred during getting access token: " + e.getMessage()); + throw e; + } + } + + /** + * Get WeSign Sign ticket. + * + * @param accessToken the access token + * @return the sign ticket + * @throws Exception any exception + */ + public static String getWeSignTicketString(String accessToken) throws Exception { + + SignTicketResponse signTicketResponse = getSignTicket(accessToken); + int code = signTicketResponse.getCode(); + String msg = signTicketResponse.getMsg(); + if (0 != code) { + logger.error( + "Error occurred during getting sign ticket. code: " + code + ", msg: " + msg); + return null; + } + return signTicketResponse.getTickets().get(0).getValue(); + } + + private static SignTicketResponse getSignTicket(String accessToken) throws Exception { + + return getSignTicket( + weSignTicketUrl + "?app_id={0}&access_token={1}&type=SIGN&version=1.0.0", + weSignAppId, + accessToken + ); + } + + private static SignTicketResponse getSignTicket(String urlExp, String appId, + String accessToken) throws Exception { + + logger.info("request arg::urlExp: {}, appId:: {}, accessToken: {}", urlExp, appId, + accessToken); + if (StringUtils.isBlank(urlExp) || StringUtils.isBlank(appId) || StringUtils + .isBlank(accessToken)) { + return null; + } + try { + String accessTokenUrl = MessageFormat.format(urlExp, appId, accessToken); + logger.debug("[getSignTicket]:{}", accessTokenUrl); + + String responseData = HttpClient.doGet(accessTokenUrl, true); + logger.info("[getSignTicket]: response: {}", responseData); + + if (StringUtils.isBlank(responseData)) { + return null; + } + return DataToolUtils.deserialize(responseData, SignTicketResponse.class); + } catch (Exception e) { + logger.error("Error occurred during getting sign ticket: " + e.getMessage()); + throw e; + } + } + + /** + * Get timestamp response. + * + * @param signTicket the sign ticket + * @param nonce the nonce value + * @param hashValue the hash value + * @return response + * @throws Exception any exception + */ + public static GetTimestampResponse getTimestamp(String signTicket, String nonce, + String hashValue) throws Exception { + return getTimestamp( + weSignTimestampUrl, + weSignAppId, + nonce, + getWeSignParam(nonce, signTicket), + hashValue + ); + } + + private static GetTimestampResponse getTimestamp(String urlExp, String appId, String nonce, + String signParam, + String hashValue) throws Exception { + + if (StringUtils.isBlank(urlExp) || StringUtils.isBlank(appId) || StringUtils + .isBlank(hashValue) || StringUtils.isBlank(nonce) || StringUtils.isBlank(signParam)) { + return null; + } + try { + String accessTokenUrl = urlExp; + GetTimestampRequest req = new GetTimestampRequest(); + req.setNonce(nonce); + req.setPlainHash(hashValue); + req.setWebankAppId(appId); + req.setSign(signParam); + String responseData = HttpClient.doPost(accessTokenUrl, req, true); + logger.info("[getTimestamp]: response: {}", responseData); + + if (StringUtils.isBlank(responseData)) { + return null; + } + return DataToolUtils.deserialize(responseData, GetTimestampResponse.class); + } catch (Exception e) { + logger.error("Error occurred during getting sign ticket: " + e.getMessage()); + throw e; + } + } + + /** + * Verify a timestamp. + * + * @param signParam the sign param + * @param nonce the nonce value + * @param hashValue the hash value + * @param timestampValue the timestamp value + * @return response + * @throws Exception any exception + */ + public static VerifyTimestampResponse verifyTimestamp(String signParam, String nonce, + String hashValue, String timestampValue) throws Exception { + return verifyTimestamp( + weSignTimestampUrl, + weSignAppId, + nonce, + signParam, + hashValue, + timestampValue + ); + } + + private static VerifyTimestampResponse verifyTimestamp(String urlExp, String appId, + String nonce, + String signParam, String hashValue, String timestampValue) throws Exception { + + if (StringUtils.isBlank(urlExp) || StringUtils.isBlank(appId) || StringUtils + .isBlank(hashValue) || StringUtils.isBlank(nonce) || StringUtils.isBlank(signParam)) { + return null; + } + try { + String accessTokenUrl = urlExp; + VerifyTimestampRequest req = new VerifyTimestampRequest(); + req.setNonce(nonce); + req.setPlainHash(hashValue); + req.setWebankAppId(appId); + req.setSign(signParam); + req.setB64TimeStamp(timestampValue); + String responseData = HttpClient.doPost(accessTokenUrl, req, true); + logger.info("[getSignTicket]: response: {}", responseData); + + if (StringUtils.isBlank(responseData)) { + return null; + } + return DataToolUtils.deserialize(responseData, VerifyTimestampResponse.class); + } catch (Exception e) { + logger.error("Error occurred during getting sign ticket: " + e.getMessage()); + throw e; + } + } + + /** + * Generate an arbitrary length nonce. + * + * @param length length + * @param num number of nonce values + * @return nonce list + */ + public static List generateNonce(int length, long num) { + + List results = new ArrayList(); + + for (int j = 0; j < num; j++) { + String val = ""; + + Random random = new Random(); + for (int i = 0; i < length; i++) { + String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; + if ("char".equalsIgnoreCase(charOrNum)) { + int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; + val += (char) (choice + random.nextInt(26)); + } else if ("num".equalsIgnoreCase(charOrNum)) { + val += String.valueOf(random.nextInt(10)); + } + } + val = val.toLowerCase(); + if (results.contains(val)) { + continue; + } else { + results.add(val); + } + } + return results; + } + + private static String sha1Sign(List values, String ticket) { + if (values == null) { + return StringUtils.EMPTY; + } + + values.removeAll(Collections.singleton(null)); + values.add(ticket); + + Collections.sort(values); + + StringBuilder sb = new StringBuilder(); + for (String s : values) { + sb.append(s); + } + return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase(); + } + + /** + * Get WeSign specific SIGN parameter. + * + * @param nonce the nonce value + * @param ticket the sign ticket value + * @return SIGN + */ + public static String getWeSignParam(String nonce, String ticket) { + ArrayList list = new ArrayList<>(); + list.add(weSignAppId); + list.add(nonce); + list.add("1.0.0"); + return sha1Sign(list, ticket); + } + + /** + * Get WeSign specific Hash based on SHA1. + * + * @param originalText original text + * @return Hash value + */ + public static String getWeSignHash(String originalText) { + return Hex + .toHexString(Hashing.sha1().hashString(originalText, Charsets.UTF_8).asBytes()); + } +} diff --git a/src/main/java/com/webank/weid/util/WeIdUtils.java b/src/main/java/com/webank/weid/util/WeIdUtils.java index bd08d235..027cbb9d 100644 --- a/src/main/java/com/webank/weid/util/WeIdUtils.java +++ b/src/main/java/com/webank/weid/util/WeIdUtils.java @@ -1,32 +1,20 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ -package com.webank.weid.util; - -import java.math.BigInteger; -import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; +package com.webank.weid.util; import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.exception.WeIdBaseException; import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.fisco.bcos.sdk.utils.Numeric; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.regex.Pattern; /** * The WeIdentity DID Utils. @@ -35,17 +23,50 @@ */ public final class WeIdUtils { + /** + * log4j object, for recording log. + */ + private static final Logger logger = LoggerFactory.getLogger(WeIdUtils.class); + + private static String getChainId() { + if (DataToolUtils.deployStyle.equals("blockchain")) { + return com.webank.weid.blockchain.util.DataToolUtils.chainId; + } else { + // default database + return "0"; + } + } + + public static CreateWeIdDataResult createWeId() { + CreateWeIdDataResult result = new CreateWeIdDataResult(); + //CryptoKeyPair keyPair = DataToolUtils.cryptoSuite.createKeyPair(); + //String publicKey = DataToolUtils.hexStr2DecStr(keyPair.getHexPublicKey()); + String privateKey = DataToolUtils.generatePrivateKey(); + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey, 10)); + WeIdPublicKey userWeIdPublicKey = new WeIdPublicKey(); + userWeIdPublicKey.setPublicKey(publicKey); + result.setUserWeIdPublicKey(userWeIdPublicKey); + WeIdPrivateKey userWeIdPrivateKey = new WeIdPrivateKey(); + userWeIdPrivateKey.setPrivateKey(privateKey); + result.setUserWeIdPrivateKey(userWeIdPrivateKey); + //替换国密 + String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); + result.setWeId(weId); + return result; + } + /** * Convert a WeIdentity DID to a fisco account address. * - * @param weid the WeIdentity DID + * @param weId the WeIdentity DID * @return weId related address, empty if input WeIdentity DID is illegal */ - public static String convertWeIdToAddress(String weid) { - if (StringUtils.isEmpty(weid) || !StringUtils.contains(weid, WeIdConstant.WEID_PREFIX)) { + public static String convertWeIdToAddress(String weId) { + if (StringUtils.isEmpty(weId) || !StringUtils.contains(weId, WeIdConstant.WEID_PREFIX)) { return StringUtils.EMPTY; } - return StringUtils.splitByWholeSeparator(weid, ":")[2]; + String[] weIdFields = StringUtils.splitByWholeSeparator(weId, WeIdConstant.WEID_SEPARATOR); + return weIdFields[weIdFields.length - 1]; } /** @@ -58,7 +79,7 @@ public static String convertAddressToWeId(String address) { if (StringUtils.isEmpty(address)) { return StringUtils.EMPTY; } - return new StringBuffer().append(WeIdConstant.WEID_PREFIX).append(address).toString(); + return buildWeIdByAddress(address); } /** @@ -68,24 +89,42 @@ public static String convertAddressToWeId(String address) { * @return true if the WeIdentity DID is legal, false otherwise. */ public static boolean isWeIdValid(String weId) { - return (StringUtils.isNotEmpty(weId) + return StringUtils.isNotEmpty(weId) && StringUtils.startsWith(weId, WeIdConstant.WEID_PREFIX) - && StringUtils.isNotEmpty(StringUtils.splitByWholeSeparator(weId, ":")[2]) - ); + && isMatchTheChainId(weId) + && isValidAddress(convertWeIdToAddress(weId)); } /** * Convert a public key to a WeIdentity DID. * - * @param publicKey the public key + * @param publicKey the public key (decimal) * @return WeIdentity DID */ public static String convertPublicKeyToWeId(String publicKey) { - String address = Keys.getAddress(new BigInteger(publicKey)); - String weId = - new StringBuffer().append(WeIdConstant.WEID_PREFIX).append("0x").append(address) - .toString(); - return weId; + try { + //String address = Keys.getAddress(new BigInteger(publicKey)); + String address = DataToolUtils.addressFromPublic(new BigInteger(publicKey)); + return buildWeIdByAddress(address); + } catch (Exception e) { + logger.error("convert publicKey to weId error.", e); + return StringUtils.EMPTY; + } + } + + private static String buildWeIdByAddress(String address) { + if (StringUtils.isEmpty(getChainId())) { + throw new WeIdBaseException("the chain Id is illegal."); + } + StringBuffer weId = new StringBuffer(); + weId.append(WeIdConstant.WEID_PREFIX) + .append(getChainId()) + .append(WeIdConstant.WEID_SEPARATOR); + if (!StringUtils.contains(address, WeIdConstant.HEX_PREFIX)) { + weId.append(WeIdConstant.HEX_PREFIX); + } + weId.append(address); + return weId.toString(); } /** @@ -95,16 +134,132 @@ public static String convertPublicKeyToWeId(String publicKey) { * @return true if the private key is not empty, false otherwise. */ public static boolean isPrivateKeyValid(WeIdPrivateKey weIdPrivateKey) { - return (null != weIdPrivateKey && StringUtils.isNotEmpty(weIdPrivateKey.getPrivateKey())); + return (null != weIdPrivateKey && StringUtils.isNotEmpty(weIdPrivateKey.getPrivateKey()) + && NumberUtils.isDigits(weIdPrivateKey.getPrivateKey()) + && new BigInteger(weIdPrivateKey.getPrivateKey()).compareTo(BigInteger.ZERO) > 0); } /** - * check if the public key matchs the private key + * check if the public key matchs the private key. + * + * @param privateKey the WeIdentity DID private key + * @param publicKey the WeIdentity DID publicKey key + * @return true if the private and publicKey key is match, false otherwise. + */ + /*public static boolean isEcdsaKeypairMatch(String privateKey, String publicKey) { + try { + *//*ECKeyPair keyPair = ECKeyPair.create(new BigInteger(privateKey)); + return StringUtils.equals(String.valueOf(keyPair.getPublicKey()), publicKey);*//* + CryptoKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate( + new BigInteger(privateKey)); + byte[] bytePub = Numeric.hexStringToByteArray(keyPair.getHexPublicKey()); + return StringUtils.equals(new BigInteger(1, bytePub).toString(), publicKey); + } catch (Exception e) { + return false; + } + }*/ + + /** + * check if the public key matchs the private key. + * + * @param privateKey BigInt of decimal private key + * @param publicKey the WeIdentity DID publicKey key decimal + * @return true if the private and publicKey key is match, false otherwise. */ - public static boolean isKeypairMatch(String privateKey, String publicKey) { + public static boolean isKeypairMatch(BigInteger privateKey, String publicKey) { + String pubFromPri = DataToolUtils.publicKeyStrFromPrivate(privateKey); + return StringUtils.equals(pubFromPri, publicKey); + } + + /** + * check if the given string is a valid address. + * + * @param addr given string + * @return true if yes, false otherwise. + */ + public static boolean isValidAddress(String addr) { + if (StringUtils.isEmpty(addr) + || !Pattern.compile(WeIdConstant.FISCO_BCOS_ADDRESS_PATTERN).matcher(addr).matches()) { + return false; + } + try { + // return WalletUtils.isValidAddress(addr); + // java-sdk去掉了WalletUtils.isValidAddress, 此处为先将原逻辑迁移出来 + String addressNoPrefix = Numeric.cleanHexPrefix(addr); + return addressNoPrefix.length() == 40; + } catch (Exception e) { + return false; + } + } + + /** + * check if the chainId. + * + * @param weId given weId + * @return true if yes, false otherwise. + */ + public static boolean isMatchTheChainId(String weId) { + String[] weIdFields = StringUtils.splitByWholeSeparator(weId, WeIdConstant.WEID_SEPARATOR); + if (weIdFields.length == 4) { + return weIdFields[2].equals(getChainId()); + } + return true; + } + + /** + * check the weId is match the private key. + * + * @param privateKey the private key + * @param weId the weId + * @return true if match, false mismatch + */ + public static boolean validatePrivateKeyWeIdMatches(WeIdPrivateKey privateKey, String weId) { + boolean isMatch = false; + + try { + String address1 = DataToolUtils.addressFromPrivate(new BigInteger(privateKey.getPrivateKey())); + String address2 = WeIdUtils.convertWeIdToAddress(weId); + if (address1.equals(address2)) { + isMatch = true; + } + } catch (Exception e) { + logger.error("Validate private key We Id matches failed. Error message :{}", e); + return false; + } + + return isMatch; + } + + /** + * get address from private key. + * + * @param privateKey private key + * @return address + */ + public static String getWeIdFromPrivateKey(String privateKey) { + /*BigInteger publicKey = DataToolUtils + .publicKeyFromPrivate(new BigInteger(privateKey));*/ + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey)); + return convertPublicKeyToWeId(publicKey); + } + + /** + * Check private key length. + * + * @param privateKey private key string in decimal + * @return true if OK, false otherwise + */ + public static boolean isPrivateKeyLengthValid(String privateKey) { + if (StringUtils.isBlank(privateKey)) { + return false; + } + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); try { - ECKeyPair keyPair = ECKeyPair.create(new BigInteger(privateKey)); - return StringUtils.equals(String.valueOf(keyPair.getPublicKey()), publicKey); + BigInteger privKeyBig = new BigInteger(privateKey, 10); + BigInteger maxPrivKeyValue = new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16); + return (privKeyBig.compareTo(maxPrivKeyValue) <= 0); } catch (Exception e) { return false; } diff --git a/src/main/java/com/webank/weid/util/keystore/KeyTool.java b/src/main/java/com/webank/weid/util/keystore/KeyTool.java new file mode 100644 index 00000000..4fe69bdd --- /dev/null +++ b/src/main/java/com/webank/weid/util/keystore/KeyTool.java @@ -0,0 +1,409 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.util.keystore; + +import com.webank.weid.exception.LoadKeyStoreException; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.jce.spec.ECPrivateKeySpec; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemWriter; +import org.fisco.bcos.web3j.utils.Numeric; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.security.*; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import java.util.Collections; + +public abstract class KeyTool { + protected static Logger logger = LoggerFactory.getLogger(KeyTool.class); + + protected final String keyStoreFile; + protected final String password; + protected KeyStore keyStore; + private String hexedPublicKey = ""; + + /** + * Constructor for the P12: with password + * + * @param keyStoreFile the path of the keystore file + * @param password password to read the keystore file + */ + public KeyTool(final String keyStoreFile, final String password) { + this.keyStoreFile = keyStoreFile; + this.password = password; + initSecurity(); + load(); + } + + /** + * Constructor for PEM without password + * + * @param keyStoreFile the path of the keystore file + */ + public KeyTool(final String keyStoreFile) { + this(keyStoreFile, null); + } + + /** + * Constructor for the P12: with password and key file input stream + * + * @param keyStoreFileInputStream the input stream of the keystore file + * @param password password to read the keystore file + */ + public KeyTool(InputStream keyStoreFileInputStream, final String password) { + this.keyStoreFile = null; + this.password = password; + initSecurity(); + this.load(keyStoreFileInputStream); + } + + /** + * Constructor for PEM with key file input stream + * + * @param keyStoreFileInputStream the input stream of the keystore file + */ + public KeyTool(InputStream keyStoreFileInputStream) { + this(keyStoreFileInputStream, null); + } + + protected abstract PrivateKey getPrivateKey(); + + private static void initSecurity() { + Security.setProperty("crypto.policy", "unlimited"); + Security.addProvider(new BouncyCastleProvider()); + } + + public final String getKeyStoreFile() { + return this.keyStoreFile; + } + + /** + * Get keyPair loaded from the keyStore file + * + * @return the keyPair + */ + public KeyPair getKeyPair() { + PrivateKey privateKey = getPrivateKey(); + PublicKey publicKey = getPublicKeyFromPrivateKey(); + return new KeyPair(publicKey, privateKey); + } + + /** + * Abstract function of getting public key + * + * @return PublicKey + */ + protected abstract PublicKey getPublicKey(); + + public static String getHexedPublicKey(PublicKey publicKey) { + byte[] publicKeyBytes = ((BCECPublicKey) publicKey).getQ().getEncoded(false); + BigInteger publicKeyValue = + new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length)); + return Numeric.toHexStringNoPrefixZeroPadded(publicKeyValue, 128); + } + + /** + * Get hex string type public key + * + * @return hex string of a public key + */ + public String getHexedPublicKey() { + if (!"".equals(hexedPublicKey)) { + return this.hexedPublicKey; + } + this.hexedPublicKey = getHexedPublicKey(getPublicKey()); + return this.hexedPublicKey; + } + + /** + * Get hex string type private key + * + * @param privateKey PrivateKey type private key + * @return the hex string type private key + */ + public static String getHexedPrivateKey(PrivateKey privateKey) { + return Numeric.toHexStringNoPrefixZeroPadded(((BCECPrivateKey) privateKey).getD(), 64); + } + + /** + * convert hexed string into PrivateKey type storePublicKeyWithPem + * + * @param hexedPrivateKey the hexed privateKey + * @param curveName the curve name + * @return the converted privateKey + * @throws LoadKeyStoreException convert exception, return exception information + */ + public static PrivateKey convertHexedStringToPrivateKey( + String hexedPrivateKey, String curveName) throws LoadKeyStoreException { + BigInteger privateKeyValue = new BigInteger(hexedPrivateKey, 16); + return convertHexedStringToPrivateKey(privateKeyValue, curveName); + } + + /** + * Convert BigInteger private key and ECC curve name to PrivateKey type key + * + * @param privateKey BigInteger type private key + * @param curveName the ECC curve name + * @return PrivateKey + */ + public static PrivateKey convertHexedStringToPrivateKey( + BigInteger privateKey, String curveName) { + return convertPrivateKeyToKeyPair(privateKey, curveName).getPrivate(); + } + + /** + * Convert string type private key integer and ECC curve name to PrivateKey type key + * + * @param hexedPrivateKey string type of the private key integer + * @param curveName ECC curve name + * @return KeyPair + * @throws LoadKeyStoreException + */ + public static KeyPair convertHexedStringToKeyPair(String hexedPrivateKey, String curveName) + throws LoadKeyStoreException { + BigInteger privateKeyValue = new BigInteger(hexedPrivateKey, 16); + return convertPrivateKeyToKeyPair(privateKeyValue, curveName); + } + + /** + * Convert BigInteger private key and ECC curve name to KeyPair + * + * @param privateKey BigInteger type private key + * @param curveName ECC curve name + * @return KeyPair + * @throws LoadKeyStoreException + */ + public static KeyPair convertPrivateKeyToKeyPair(BigInteger privateKey, String curveName) + throws LoadKeyStoreException { + try { + initSecurity(); + org.bouncycastle.jce.spec.ECParameterSpec ecParameterSpec = + ECNamedCurveTable.getParameterSpec(curveName); + ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(privateKey, ecParameterSpec); + KeyFactory keyFactory = + KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + // get private key + BCECPrivateKey privateKeyObject = + (BCECPrivateKey) keyFactory.generatePrivate(privateKeySpec); + PublicKey publicKey = getPublicKeyFromPrivateKey(privateKeyObject); + ECPrivateKeyParameters ecPrivateKeyParameters = + new ECPrivateKeyParameters( + privateKeyObject.getD(), + new ECDomainParameters( + ecParameterSpec.getCurve(), + ecParameterSpec.getG(), + ecParameterSpec.getN())); + BCECPrivateKey bcecPrivateKey = + new BCECPrivateKey( + privateKeyObject.getAlgorithm(), + ecPrivateKeyParameters, + (BCECPublicKey) publicKey, + ecParameterSpec, + BouncyCastleProvider.CONFIGURATION); + return new KeyPair(publicKey, bcecPrivateKey); + } catch (NoSuchProviderException | InvalidKeySpecException | NoSuchAlgorithmException e) { + throw new LoadKeyStoreException( + "covert private key into PrivateKey type failed, " + + " error information: " + + e.getMessage(), + e); + } + } + + /** + * Generate public key from private key, and store public key in to pem key file + * + * @param privateKey a private key + * @param privateKeyFilePath the pem key file + * @throws IOException + */ + public static void storePublicKeyWithPem(PrivateKey privateKey, String privateKeyFilePath) + throws IOException { + PublicKey publicKey = getPublicKeyFromPrivateKey(privateKey); + storePublicKeyWithPem(publicKey, privateKeyFilePath); + } + + /** + * Store public key in to pem key file + * + * @param publicKey a public key + * @param privateKeyFilePath the pem key file + * @throws IOException + */ + public static void storePublicKeyWithPem(PublicKey publicKey, String privateKeyFilePath) + throws IOException { + String publicKeyPath = privateKeyFilePath + ".pub"; + PemWriter writer = new PemWriter(new FileWriter(publicKeyPath)); + writer.writeObject(new PemObject("PUBLIC KEY", publicKey.getEncoded())); + writer.flush(); + writer.close(); + } + + /** + * Abstract function of load key from InputStream + * + * @param in the InputStream + */ + protected abstract void load(InputStream in); + + /** load information from the keyStoreFile */ + protected void load() { + try { + InputStream keyStoreFileInputStream = new FileInputStream(keyStoreFile); + this.load(keyStoreFileInputStream); + } catch (FileNotFoundException | org.bouncycastle.util.encoders.DecoderException e) { + String errorMessage = + "load keys from " + + keyStoreFile + + " failed for FileNotFoundException, error message:" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + } + + private static Method getMethod( + Class ec5UtilClass, String methodName, Class... parameterTypes) { + try { + return ec5UtilClass.getDeclaredMethod(methodName, parameterTypes); + } catch (NoSuchMethodException e) { + logger.debug("try to get method for EC5Util failed, method name: {}", methodName); + return null; + } + } + + private static org.bouncycastle.jce.spec.ECParameterSpec convertToECParamSpec( + ECParameterSpec _ecParams) throws LoadKeyStoreException { + try { + Class ec5UtilClass = EC5Util.class; + String methodName = "convertSpec"; + Object ecParamSpec = null; + Object ec5utilObject = ec5UtilClass.newInstance(); + Method methodDeclare = getMethod(ec5UtilClass, methodName, ECParameterSpec.class); + if (methodDeclare != null) { + ecParamSpec = methodDeclare.invoke(ec5utilObject, _ecParams); + + } else { + methodDeclare = + getMethod(ec5UtilClass, methodName, ECParameterSpec.class, boolean.class); + if (methodDeclare != null) { + ecParamSpec = methodDeclare.invoke(ec5utilObject, _ecParams, false); + } + } + if (ecParamSpec != null) { + return (org.bouncycastle.jce.spec.ECParameterSpec) ecParamSpec; + } + logger.error( + "convertToECParamSpec exception for {} not found, supported methodList: {}", + methodName, + (ec5UtilClass.getMethods() != null + ? ec5UtilClass.getMethods().toString() + : " none")); + throw new LoadKeyStoreException( + "convertToECParamSpec exception for " + + methodName + + " not found! Please check the version of bcprov-jdk15on!"); + } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { + logger.error( + "convertToECParamSpec exception, error: {}, e: {}", + e.getMessage(), + e.getStackTrace().toString()); + throw new LoadKeyStoreException("convertToECParamSpec exception for " + e.getMessage()); + } + } + + /** + * Get the public key + * + * @return PublicKey + */ + protected PublicKey getPublicKeyFromPrivateKey() { + return getPublicKeyFromPrivateKey(getPrivateKey()); + } + + /** + * Generate and get the public key from private key + * + * @param privateKey the PrivateKey + * @return the PublicKey + * @throws LoadKeyStoreException + */ + public static PublicKey getPublicKeyFromPrivateKey(PrivateKey privateKey) + throws LoadKeyStoreException { + try { + initSecurity(); + ECPrivateKey ecPrivateKey = (ECPrivateKey) privateKey; + ECParameterSpec params = ecPrivateKey.getParams(); + + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = convertToECParamSpec(params); + org.bouncycastle.math.ec.ECPoint q = bcSpec.getG().multiply(ecPrivateKey.getS()); + org.bouncycastle.math.ec.ECPoint bcW = + bcSpec.getCurve().decodePoint(q.getEncoded(false)); + ECPoint w = + new ECPoint( + bcW.getAffineXCoord().toBigInteger(), + bcW.getAffineYCoord().toBigInteger()); + ECPublicKeySpec keySpec = new ECPublicKeySpec(w, tryFindNamedCurveSpec(params)); + return (PublicKey) + KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME) + .generatePublic(keySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { + String errorMessage = + "get publicKey from given the private key failed, error message:" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + } + + @SuppressWarnings("unchecked") + private static ECParameterSpec tryFindNamedCurveSpec(ECParameterSpec params) + throws LoadKeyStoreException { + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = convertToECParamSpec(params); + for (Object name : Collections.list(ECNamedCurveTable.getNames())) { + ECNamedCurveParameterSpec bcNamedSpec = + ECNamedCurveTable.getParameterSpec((String) name); + if (bcNamedSpec.getN().equals(bcSpec.getN()) + && bcNamedSpec.getH().equals(bcSpec.getH()) + && bcNamedSpec.getCurve().equals(bcSpec.getCurve()) + && bcNamedSpec.getG().equals(bcSpec.getG())) { + return new ECNamedCurveSpec( + bcNamedSpec.getName(), + bcNamedSpec.getCurve(), + bcNamedSpec.getG(), + bcNamedSpec.getN(), + bcNamedSpec.getH(), + bcNamedSpec.getSeed()); + } + } + return params; + } +} diff --git a/src/main/java/com/webank/weid/util/keystore/P12KeyStore.java b/src/main/java/com/webank/weid/util/keystore/P12KeyStore.java new file mode 100644 index 00000000..dd6c9400 --- /dev/null +++ b/src/main/java/com/webank/weid/util/keystore/P12KeyStore.java @@ -0,0 +1,200 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.util.keystore; + +import com.webank.weid.exception.LoadKeyStoreException; +import com.webank.weid.exception.SaveKeyStoreException; +import org.bouncycastle.crypto.tls.SignatureAlgorithm; +import org.bouncycastle.jce.X509Principal; +import org.bouncycastle.x509.X509V3CertificateGenerator; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Enumeration; + +public class P12KeyStore extends KeyTool { + private static final String NAME = "key"; + private KeyStore keyStore; + + public P12KeyStore(final String keyStoreFile, final String password) { + super(keyStoreFile, password); + } + + public P12KeyStore(InputStream keyStoreFileInputStream, final String password) { + super(keyStoreFileInputStream, password); + } + + @Override + public PublicKey getPublicKey() { + try { + Enumeration aliases = keyStore.aliases(); + Certificate certificate = null; + while (aliases.hasMoreElements() && certificate == null) { + certificate = keyStore.getCertificate(aliases.nextElement()); + } + if (certificate == null) { + throw new LoadKeyStoreException( + "getPublicKey from p12 file " + keyStoreFile + "failed"); + } + return certificate.getPublicKey(); + } catch (KeyStoreException e) { + throw new LoadKeyStoreException( + "getPublicKey from p12 file " + + keyStoreFile + + " failed, error message: " + + e.getMessage(), + e); + } + } + + /** + * load keyPair from the given input stream + * + * @param in the input stream that should used to load keyPair + */ + @Override + protected void load(InputStream in) { + try { + keyStore = KeyStore.getInstance("PKCS12", "BC"); + String password = ""; + if (this.password != null) { + password = this.password; + } + keyStore.load(in, password.toCharArray()); + + } catch (IOException + | CertificateException + | NoSuchAlgorithmException + | NoSuchProviderException + | KeyStoreException e) { + String errorMessage = + "load keys from p12 file " + + keyStoreFile + + " failed, error message:" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + } + + /** + * get private key from the keyStore + * + * @return the private key + */ + @Override + protected PrivateKey getPrivateKey() { + try { + Enumeration aliases = keyStore.aliases(); + PrivateKey privateKey = null; + while (aliases.hasMoreElements() && privateKey == null) { + privateKey = + (PrivateKey) keyStore.getKey(aliases.nextElement(), password.toCharArray()); + } + if (privateKey == null) { + throw new LoadKeyStoreException( + "getPrivateKey from p12 file " + keyStoreFile + "failed"); + } + return privateKey; + } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) { + String errorMessage = + "get private key from " + + keyStoreFile + + " failed for UnrecoverableKeyException, error message" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + } + + public static void storeKeyPairWithP12Format( + String hexedPrivateKey, + String password, + String privateKeyFilePath, + String curveName, + String signatureAlgorithm) + throws SaveKeyStoreException { + try { + hexedPrivateKey = hexedPrivateKey.startsWith("0x") ? hexedPrivateKey.substring(2) : hexedPrivateKey; + PrivateKey privateKey = convertHexedStringToPrivateKey(hexedPrivateKey, curveName); + // save the private key + KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); + // load to init the keyStore + keyStore.load(null, password.toCharArray()); + KeyPair keyPair = new KeyPair(getPublicKeyFromPrivateKey(privateKey), privateKey); + // Since KeyStore setEntry must set the certificate chain, a self-signed certificate is + // generated + Certificate[] certChain = new Certificate[1]; + certChain[0] = generateSelfSignedCertificate(keyPair, signatureAlgorithm); + keyStore.setKeyEntry(NAME, privateKey, password.toCharArray(), certChain); + keyStore.store(new FileOutputStream(privateKeyFilePath), password.toCharArray()); + // store the public key + storePublicKeyWithPem(privateKey, privateKeyFilePath); + } catch (IOException + | KeyStoreException + | NoSuchProviderException + | NoSuchAlgorithmException + | CertificateException + | LoadKeyStoreException + | InvalidKeyException + | SignatureException e) { + throw new SaveKeyStoreException( + "save private key into " + + privateKeyFilePath + + " failed, error information: " + + e.getMessage(), + e); + } + } + + /** + * generate self-signed certificate + * + * @param keyPair the keyPair used to generated the certificate + * @param signatureAlgorithm the signature algorithm of the cert + * @return the generated self-signed certificate object + * @throws NoSuchAlgorithmException no such algorithm exception + * @throws CertificateEncodingException error occurs when encoding certificate + * @throws NoSuchProviderException no such provider exception + * @throws InvalidKeyException invalid key exception + * @throws SignatureException generic signature exception + */ + public static X509Certificate generateSelfSignedCertificate( + KeyPair keyPair, String signatureAlgorithm) + throws NoSuchAlgorithmException, CertificateEncodingException, NoSuchProviderException, + InvalidKeyException, SignatureException { + X509V3CertificateGenerator cert = new X509V3CertificateGenerator(); + cert.setSerialNumber(BigInteger.valueOf(1)); // or generate a random number + cert.setSubjectDN(new X509Principal("CN=localhost")); // see examples to add O,OU etc + cert.setIssuerDN(new X509Principal("CN=localhost")); // same since it is self-signed + cert.setPublicKey(keyPair.getPublic()); + Calendar notBefore = Calendar.getInstance(); + Calendar notAfter = Calendar.getInstance(); + notBefore.add(Calendar.YEAR, 100); + cert.setNotBefore(notBefore.getTime()); + cert.setNotAfter(notAfter.getTime()); + cert.setSignatureAlgorithm(signatureAlgorithm); + cert.setPublicKey(keyPair.getPublic()); + PrivateKey signingKey = keyPair.getPrivate(); + return cert.generate(signingKey, "BC"); + } +} diff --git a/src/main/java/com/webank/weid/util/keystore/PEMKeyStore.java b/src/main/java/com/webank/weid/util/keystore/PEMKeyStore.java new file mode 100644 index 00000000..f196bc4d --- /dev/null +++ b/src/main/java/com/webank/weid/util/keystore/PEMKeyStore.java @@ -0,0 +1,125 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.webank.weid.util.keystore; + +import com.webank.weid.exception.LoadKeyStoreException; +import com.webank.weid.exception.SaveKeyStoreException; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.bouncycastle.util.io.pem.PemWriter; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +public class PEMKeyStore extends KeyTool { + public static final String PRIVATE_KEY = "PRIVATE KEY"; + private PemObject pem; + + public PEMKeyStore(final String keyStoreFile) { + super(keyStoreFile); + } + + public PEMKeyStore(InputStream keyStoreFileInputStream) { + super(keyStoreFileInputStream); + } + + @Override + protected PublicKey getPublicKey() { + try { + X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(pem.getContent()); + KeyFactory keyFactory = + KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + return keyFactory.generatePublic(encodedKeySpec); + } catch (InvalidKeySpecException | NoSuchProviderException | NoSuchAlgorithmException e) { + throw new LoadKeyStoreException( + "getPublicKey from pem file " + + keyStoreFile + + " failed, error message: " + + e.getMessage(), + e); + } + } + + public static void storeKeyPairWithPemFormat( + String hexedPrivateKey, String privateKeyFilePath, String curveName) + throws SaveKeyStoreException { + try { + hexedPrivateKey = hexedPrivateKey.startsWith("0x") ? hexedPrivateKey.substring(2) : hexedPrivateKey; + KeyPair keyPair = convertHexedStringToKeyPair(hexedPrivateKey, curveName); + // save the private key + PemWriter writer = new PemWriter(new FileWriter(privateKeyFilePath)); + BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) (keyPair.getPrivate()); + writer.writeObject(new PemObject(PRIVATE_KEY, bcecPrivateKey.getEncoded())); + writer.flush(); + writer.close(); + // write the public key + storePublicKeyWithPem(keyPair.getPublic(), privateKeyFilePath); + } catch (IOException | LoadKeyStoreException e) { + throw new SaveKeyStoreException( + "save keys into " + + privateKeyFilePath + + " failed, error information: " + + e.getMessage(), + e); + } + } + + @Override + protected void load(InputStream in) { + try { + PemReader pemReader = new PemReader(new InputStreamReader(in)); + pem = pemReader.readPemObject(); + pemReader.close(); + } catch (IOException e) { + String errorMessage = + "load key info from the pem file " + + keyStoreFile + + " failed, error message:" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + if (pem == null) { + logger.error("The file " + keyStoreFile + " does not represent a pem account."); + throw new LoadKeyStoreException("The file does not represent a pem account."); + } + } + + @Override + protected PrivateKey getPrivateKey() { + try { + PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(pem.getContent()); + KeyFactory keyFacotry = + KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + return keyFacotry.generatePrivate(encodedKeySpec); + } catch (InvalidKeySpecException | NoSuchProviderException | NoSuchAlgorithmException e) { + String errorMessage = + "getPrivateKey from pem file " + + keyStoreFile + + " failed, error message:" + + e.getMessage(); + logger.error(errorMessage); + throw new LoadKeyStoreException(errorMessage, e); + } + } + +} diff --git a/src/main/resources/applicationContext.xml.tpl b/src/main/resources/applicationContext.xml.tpl deleted file mode 100644 index 33e00e7a..00000000 --- a/src/main/resources/applicationContext.xml.tpl +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - ${WEID_ADDRESS} - ${CPT_ADDRESS} - ${ISSUER_ADDRESS} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${BLOCKCHIAN_NODE_INFO} - - - - - - - - diff --git a/src/main/resources/ca.crt b/src/main/resources/ca.crt deleted file mode 100644 index 3b25e342..00000000 --- a/src/main/resources/ca.crt +++ /dev/null @@ -1,43 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIJAKzDiIgxxWh7MA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV -BAMMAkNOMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQH -DAhTaGVuemhlbjETMBEGA1UECgwKRklTQ08tQkNPUzEOMAwGA1UECwwFY2hhaW4w -HhcNMTgxMTIxMDQzMzEyWhcNMjgxMTE4MDQzMzEyWjBmMQswCQYDVQQDDAJDTjEL -MAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UEBwwIU2hlbnpo -ZW4xEzARBgNVBAoMCkZJU0NPLUJDT1MxDjAMBgNVBAsMBWNoYWluMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnE6h+e8IBVLAFUcbugBk6LkcET72rGXK -BAD5c/P28UmEs8OM3B4wAJ9hBeXXhazsVFRxjf5Z63opJj2u631JsU9+rEGYXgx4 -79qpmUY/p2IgNnU2kkU7mBlgUsGH5bT75OQZogEanefBwCp/O7spOwW009I5OrU8 -Feyp3i1nEwGC6rZpR8orSt0uKISopSfsl0THi9teHjxv5d86f0EvwFMqQr2WRt1s -QH5AnIvpCL0T0c5BuTyfogAhDQyUef4NF1BLdlSygSQU3ucqSDY2LkKH3eL30rEf -RYIwEOdUQ24mcA48z4vTWmvZ1aJnkS3WZ2LO4Kzp9S33X0hpsbISNQIDAQABo1Aw -TjAdBgNVHQ4EFgQUIvulUoewmh6dEgIE2pAWmxeZCs4wHwYDVR0jBBgwFoAUIvul -Uoewmh6dEgIE2pAWmxeZCs4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAS0op04lG+atcitBbnCN9f23RbQ8JtBgJwFLMtQROX5sPzH+Yl0x/wpkbzPRC -c5ieJjnW4TsCAJdpVr9jwRxVJbE081zKmnNzdUlm80z8IlFjQ8bLjnIHjPfyoSuS -TFiEc9tLpXOhDRC9gq+niEkMFrnEWjO6TPlmnfX7o2dX+O9pK+NEjWKKt7QX5WEv -Zw1/AL6y7yf3RaC9gsOprOTD9hxF5QE1X6NUCqsY7a9Xrnt3DNQT1zhx2VoeC5RQ -svwb1YZ+3nGxU+gydrOkfiuO15+D7bN4dT+0O2/NgKZTtwSdq6ac2AQWxDN4yrgJ -9R3Cf2FY+6Ul1CV1hkOM0Y/kOg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgIJAJr9xZen9UkUMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV -BAMMAkNOMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQH -DAhTaGVuemhlbjETMBEGA1UECgwKRklTQ08tQkNPUzEOMAwGA1UECwwFY2hhaW4w -HhcNMTgxMTIxMDQzMzEyWhcNMjgxMTE4MDQzMzEyWjBmMQswCQYDVQQDDAJDTjEL -MAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UEBwwIU2hlbnpo -ZW4xEzARBgNVBAoMCkZJU0NPLUJDT1MxDjAMBgNVBAsMBWFnZW50MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvn5UikSp0LXdNkQer0PjL64HKLgRzcit -eAePXCuFxlmE2eEsuzot9h+Ucvs8GsLF/hGl1dsjKLdgw5VUCSTq70gbYOPXyThv -hy1YXqq+0Up56INZTlYCH/UQT9y5hJGNDBI0OD21nxCmmvMF38vkjhkZ8dGUG6Bp -rerbztg3lnHPaZXKWsYuS9+bUjZotUdOSyBiRrqKZPWD4wd84pjtAuoK8NjGz8ng -K2/EywvhXVfAUgoje+ydzkG/I/OvCZ/LpeaImznuG+5wiESp1wFbrmFNk6k1mKn3 -4m89Gq3CvtRujaRjkPEimnXxmq2Y10C0w43V5WlXYmIJfFRzgryseQIDAQABoxAw -DjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAM0DWpfwvCWbbLGPKF -U8KPPQSIpQJuHOMNbqNqWatoKmKpf6PHL+26EzXQIn31q1y7X6evu47628kOT6Yl -Ph2a08IVubjLQF2ru3NuGAcFqaIIYk+y0h73G4VPWx4CkvHxqodEPUMxGkgs/Q8n -DygRuIKrsj/nVW+soHH5HhaWXLJukL1xDQT8uSVfLI5aQ9IiXQI0mlTk9CC4dOea -W7xmG1pk5qWQtGPOHMrhoFfo3iX+eR+FhFRU4BFKAaPWVZvjxUHokRm8JoAChvSQ -J2im11/thyvYwbxDV9ImnmGphvfkE4iHPmCINK1Ww7WJ29f+/kEN1FN3tgcs6TSk -ambD ------END CERTIFICATE----- diff --git a/src/main/resources/client.keystore b/src/main/resources/client.keystore deleted file mode 100644 index 8d202d93..00000000 Binary files a/src/main/resources/client.keystore and /dev/null differ diff --git a/src/main/resources/consumer_private_key.p12 b/src/main/resources/consumer_private_key.p12 new file mode 100644 index 00000000..f30f29c7 Binary files /dev/null and b/src/main/resources/consumer_private_key.p12 differ diff --git a/src/main/resources/consumer_public_key.pem b/src/main/resources/consumer_public_key.pem new file mode 100644 index 00000000..fcfb8acc --- /dev/null +++ b/src/main/resources/consumer_public_key.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvpEMM5l37k2izwbs+i+T3ydnqVRG7wXq +Cpnn1fEXZa0Vr1NWJ+8bE9UpY2ZdGWkl/uH3j/yWp3L+8LofDv0wug== +-----END PUBLIC KEY----- diff --git a/src/main/resources/endpoint-data.properties b/src/main/resources/endpoint-data.properties new file mode 100644 index 00000000..e69de29b diff --git a/src/main/resources/fisco.properties b/src/main/resources/fisco.properties new file mode 100644 index 00000000..09252566 --- /dev/null +++ b/src/main/resources/fisco.properties @@ -0,0 +1,66 @@ +# Fisco-bcos blockchain node related properties + +####################################################################################################### +# # +# fisco bcos version config # +# # +####################################################################################################### +# Version +bcos.version=2 + + +####################################################################################################### +# # +# contract address config # +# # +####################################################################################################### +# contract address +weId.contractaddress= +cpt.contractaddress= +issuer.contractaddress= +evidence.contractaddress= +specificissuer.contractaddress= + +# This variable is used to distinguish the environment. You can use "dev" to set the development environment, +# "stg" to set the test environment, "prd" to set the production environment, +# If you do not set it, the system will use allOrg as the environment by default. +# It is not recommended. Production use default configuration +cns.profile.active=prdabce + +####################################################################################################### +# # +# web3sdk connection config # +# # +####################################################################################################### +# blockchain connection params +web3sdk.timeout=30 +web3sdk.core-pool-size=100 +web3sdk.max-pool-size=200 +web3sdk.queue-capacity=1000 +web3sdk.keep-alive-seconds=60 + + +####################################################################################################### +# # +# fisco bcos 2.0 && 3.0 related config # +# # +####################################################################################################### +# Fisco-Bcos 2.x params, including Group ID and Encrypt Type +# Fisco-Bcos 3.x Group Id can be String +group.id=1 + +####################################################################################################### +# # +# fisco bcos node cert related config # +# # +####################################################################################################### +# Fisco-Bcos sdk SSL encrypt type, 0:ECDSA, 1:SM2 +sdk.sm-crypto=0 +# fisco-bcos sdk cert path contains[ca.crt,sdk.crt,sdk.key] +# if sdk.sm-crypto is true, contains [gm] directory, and gm dir contains [gmca.crt,gmsdk.crt,gmsdk.key,gmensdk.crt,gmensdk.key] +sdk.cert-path=resources/conf + +# amop public key of pem and private key of p12 configuration +amop.pub-path=resources/conf/amop/consumer_public_key.pem +amop.pri-path=resources/conf/amop/consumer_private_key.p12 +amop.p12-password=123456 \ No newline at end of file diff --git a/src/main/resources/fisco.properties.tpl b/src/main/resources/fisco.properties.tpl new file mode 100644 index 00000000..7b30f59c --- /dev/null +++ b/src/main/resources/fisco.properties.tpl @@ -0,0 +1,66 @@ +# Fisco-bcos blockchain node related properties + +####################################################################################################### +# # +# fisco bcos 2 or 3 version config # +# # +####################################################################################################### +# Version +bcos.version=${FISCO_BCOS_VERSION} + + +####################################################################################################### +# # +# contract address config # +# # +####################################################################################################### +# contract address +weId.contractaddress= +cpt.contractaddress= +issuer.contractaddress= +evidence.contractaddress= +specificissuer.contractaddress= + +# This variable is used to distinguish the environment. You can use "dev" to set the development environment, +# "stg" to set the test environment, "prd" to set the production environment, +# If you do not set it, the system will use allOrg as the environment by default. +# It is not recommended. Production use default configuration +cns.profile.active=${CNS_PROFILE_ACTIVE} + +####################################################################################################### +# # +# web3sdk connection config # +# # +####################################################################################################### +# blockchain connection params +web3sdk.timeout=30 +web3sdk.core-pool-size=100 +web3sdk.max-pool-size=200 +web3sdk.queue-capacity=1000 +web3sdk.keep-alive-seconds=60 + + +####################################################################################################### +# # +# fisco bcos 2.0 && 3.0 related config # +# # +####################################################################################################### +# Fisco-Bcos 2.x params, including Group ID and Encrypt Type +# Fisco-Bcos 3.x Group Id can be String +group.id=${GROUP_ID} + +####################################################################################################### +# # +# fisco bcos node cert related config # +# # +####################################################################################################### +# Fisco-Bcos sdk SSL encrypt type, 0:ECDSA, 1:SaM2 +sdk.sm-crypto=${SDK_SM_CRYPTO} +# fisco-bcos sdk cert path contains[ca.crt,sdk.crt,sdk.key] +# if sdk.sm-crypto is true, contains [gm] directory, and gm dir contains [gmca.crt,gmsdk.crt,gmsdk.key,gmensdk.crt,gmensdk.key] +sdk.cert-path=resources/conf + +# amop public key of pem and private key of p12 configuration +amop.pub-path=resources/conf/amop/consumer_public_key.pem +amop.pri-path=resources/conf/amop/consumer_private_key.p12 +amop.p12-password=123456 diff --git a/src/main/resources/private_key b/src/main/resources/private_key new file mode 100644 index 00000000..3bceba5a --- /dev/null +++ b/src/main/resources/private_key @@ -0,0 +1 @@ +49191370627614877492996337821917274297863513005433547861103892894089436256261 \ No newline at end of file diff --git a/src/main/resources/public_key b/src/main/resources/public_key new file mode 100644 index 00000000..aec4b2e3 --- /dev/null +++ b/src/main/resources/public_key @@ -0,0 +1 @@ +5686332858406600098574930615286920155179124750677701187633916230205742334882670952535475018419229666394535946783087534972161773024961235927824774898541110 \ No newline at end of file diff --git a/src/main/resources/weidentity.properties b/src/main/resources/weidentity.properties new file mode 100644 index 00000000..7c0c19cd --- /dev/null +++ b/src/main/resources/weidentity.properties @@ -0,0 +1,159 @@ +####################################################################################################### +# # +# application config # +# # +####################################################################################################### +# Deploy WeIdentity with blockchain or only database +deploy.style= +# Crypto type, only use for deploy with database, 0 for ECDSA, 1 for SM +crypto.type= + +# The organization ID for AMOP communication. +blockchain.orgid= + +# The Blockchain Type +blockchain.type= + +# The Chain Id +chain.id= + +# AMOP Config +# Timeout for amop request, default: 5000ms +amop.request.timeout=5000 + +amop.id= + +# Blockchain node info. +nodes= + + +####################################################################################################### +# # +# persistence config # +# # +####################################################################################################### +# Persistence Layer configurations. Do NOT change this if you are not using Persistence Layer features! +#Support the persistence of mysql , redis or ipfs. You can choose the type of persistence. +persistence_type= + +# MySQL connection config +# Support multiple data source configurations with comma-separated multiple data sources. +datasource.name= + +# The configuration of each data source is prefixed by the name of the data source. +datasource1.jdbc.url=jdbc:mysql:///?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai +datasource1.jdbc.driver=com.mysql.cj.jdbc.Driver +datasource1.jdbc.username=ljh +datasource1.jdbc.password=password +datasource1.jdbc.maxActive=50 +datasource1.jdbc.initialSize=5 +datasource1.jdbc.minIdle=5 +datasource1.jdbc.maxIdle=5 +datasource1.jdbc.maxWait=10000 +datasource1.jdbc.timeBetweenEvictionRunsMillis=600000 +datasource1.jdbc.numTestsPerEvictionRun=5 +datasource1.jdbc.minEvictableIdleTimeMillis=1800000 + +# Redis config +# If you want to configure redis in cluster mode, enter multiple node addresses separated by commas. +redis.url= +redis.password= +redis_single.database=0 +redis_cluster.idle_connection_timeout=10000 +redis_cluster.connect_timeout=10000 +redis_cluster.timeout=3000 +redis_cluster.slave_connection_minimum_idle_size=10 +redis_cluster.slave_connection_pool_size=64 +redis_cluster.master_connection_minimum_idle_size=10 +redis_cluster.master_connection_pool_size=64 + +#ipfs config +# enter your IPFS node api +ipfs.api= + +####################################################################################################### +# # +# persistence domain config # +# # +####################################################################################################### +# Domain configuration, which divides colons into two segments, the first segment is the name of the data source, +# the second segment is the name of the table, and if not, the default is the first data source and the default table `sdk_all_data`, +# Multiple domains can be configured at the same time. +# example: +# domain.credential=datasource1:credential_info +# domain.credential.timeout=86400000 +# domain.weIdDocument=datasource1:weid_document_info +# domain.credential.timeout=86400000 + +# the default domain +domain.defaultInfo=datasource1:default_info +domain.defaultInfo.timeout=31556908799941 + +# the domain for save encrypt Key +domain.encryptKey=datasource1:encrypt_key_info +domain.encryptKey.timeout=31556908799941 + +# zkp credential template secret +domain.templateSecret=***REMOVED*** +domain.templateSecret.timeout=31556908799941 + +# zkp credential master secret +domain.masterKey=***REMOVED*** + +# zkp credential signature +domain.credentialSignature=datasource1:credential_signature + +# weid auth info +domain.weIdAuth=datasource1:weid_auth + +# the domain for save resource +domain.resourceInfo=datasource1:resource_info +domain.resourceInfo.timeout=31556908799941 + +# tables for running locally +local.weIdDocument=datasource1:table_weid_document +local.cpt=datasource1:table_cpt +local.policy=datasource1:table_policy +local.presentation=datasource1:table_presentation +local.role=datasource1:table_role +local.authorityIssuer=datasource1:table_authority_issuer +local.specificIssuer=datasource1:table_specific_issuer +local.evidence=datasource1:table_evidence + + +####################################################################################################### +# # +# credential related config # +# # +####################################################################################################### +# You can configure the maximumSize of the default cache module through caffeineCache.maximumSize.xxx. +caffeineCache.maximumSize.SYS_CPT=100 + +# Salt length for Proof creation. +salt.length=5 + +# Default length of array value in CPT when creating credential based on ZKP. +zkp.cpt.array.length=5 + + +####################################################################################################### +# # +# endpoint Service config # +# # +####################################################################################################### +# Endpoint Service Integration-side parameters +# Listener port required to be opened for RPC Server, default: 6010 +endpoint.listener.port=6010 + + +####################################################################################################### +# # +# timestamp Service config # +# # +####################################################################################################### +# Timestamp Service Parameters +wesign.accessTokenUrl= +wesign.signTicketUrl= +wesign.timestampUrl= +wesign.appId= +wesign.secret= \ No newline at end of file diff --git a/src/main/resources/weidentity.properties.tpl b/src/main/resources/weidentity.properties.tpl new file mode 100644 index 00000000..70340ef7 --- /dev/null +++ b/src/main/resources/weidentity.properties.tpl @@ -0,0 +1,156 @@ +####################################################################################################### +# # +# application config # +# # +####################################################################################################### +# Deploy WeIdentity with blockchain or only database +deploy.style=${DEPLOY_STYLE} +# Crypto type, only use for deploy with database, 0 for ECDSA, 1 for SM +crypto.type=${CRYPTO_TYPE} + +# The organization ID for AMOP communication. +blockchain.orgid=${ORG_ID} + +# The Blockchain Type +blockchain.type=${CHAIN_TYPE} + +# The Chain Id +chain.id=${CHAIN_ID} + +# AMOP Config +# Timeout for amop request, default: 5000ms +amop.request.timeout=5000 + +amop.id=${AMOP_ID} + +# Blockchain node info. +nodes=${BLOCKCHIAN_NODE_INFO} + + +####################################################################################################### +# # +# persistence config # +# # +####################################################################################################### +# Persistence Layer configurations. Do NOT change this if you are not using Persistence Layer features! +#Support the persistence of mysql and redis. You can choose the type of persistence. +persistence_type=${PERSISTENCE_TYPE} + +# MySQL connection config +# Support multiple data source configurations with comma-separated multiple data sources. +datasource.name=datasource1 + +# The configuration of each data source is prefixed by the name of the data source. +datasource1.jdbc.url=jdbc:mysql://${MYSQL_ADDRESS}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai +datasource1.jdbc.driver=com.mysql.cj.jdbc.Driver +datasource1.jdbc.username=${MYSQL_USERNAME} +datasource1.jdbc.password=${MYSQL_PASSWORD} +datasource1.jdbc.maxActive=50 +datasource1.jdbc.initialSize=5 +datasource1.jdbc.minIdle=5 +datasource1.jdbc.maxIdle=5 +datasource1.jdbc.maxWait=10000 +datasource1.jdbc.timeBetweenEvictionRunsMillis=600000 +datasource1.jdbc.numTestsPerEvictionRun=5 +datasource1.jdbc.minEvictableIdleTimeMillis=1800000 + +# Redis config +# If you want to configure redis in cluster mode, enter multiple node addresses separated by commas. +redis.url=${REDIS_ADDRESS} +redis.password=${REDIS_PASSWORD} +redis_single.database=0 +redis_cluster.idle_connection_timeout=10000 +redis_cluster.connect_timeout=10000 +redis_cluster.timeout=3000 +redis_cluster.slave_connection_minimum_idle_size=10 +redis_cluster.slave_connection_pool_size=64 +redis_cluster.master_connection_minimum_idle_size=10 +redis_cluster.master_connection_pool_size=64 + + +####################################################################################################### +# # +# persistence domain config # +# # +####################################################################################################### +# Domain configuration, which divides colons into two segments, the first segment is the name of the data source, +# the second segment is the name of the table, and if not, the default is the first data source and the default table `sdk_all_data`, +# Multiple domains can be configured at the same time. +# example: +# domain.credential=datasource1:credential_info +# domain.credential.timeout=86400000 +# domain.weIdDocument=datasource1:weid_document_info +# domain.credential.timeout=86400000 + +# the default domain +domain.defaultInfo=datasource1:default_info +domain.defaultInfo.timeout=31556908799941 + +# the domain for save encrypt Key +domain.encryptKey=datasource1:encrypt_key_info +domain.encryptKey.timeout=31556908799941 + +# zkp credential template secret +domain.templateSecret=***REMOVED*** +domain.templateSecret.timeout=31556908799941 + +# zkp credential master secret +domain.masterKey=***REMOVED*** + +# zkp credential signature +domain.credentialSignature=datasource1:credential_signature + +# weid auth info +domain.weIdAuth=datasource1:weid_auth + +# the domain for save resource +domain.resourceInfo=datasource1:resource_info +domain.resourceInfo.timeout=31556908799941 + +# tables for running locally +local.weIdDocument=datasource1:table_weid_document +local.cpt=datasource1:table_cpt +local.policy=datasource1:table_policy +local.presentation=datasource1:table_presentation +local.role=datasource1:table_role +local.authorityIssuer=datasource1:table_authority_issuer +local.specificIssuer=datasource1:table_specific_issuer +local.evidence=datasource1:table_evidence + + +####################################################################################################### +# # +# credential related config # +# # +####################################################################################################### +# You can configure the maximumSize of the default cache module through caffeineCache.maximumSize.xxx. +caffeineCache.maximumSize.SYS_CPT=100 + +# Salt length for Proof creation. +salt.length=5 + +# Default length of array value in CPT when creating credential based on ZKP. +zkp.cpt.array.length=5 + + +####################################################################################################### +# # +# endpoint Service config # +# # +####################################################################################################### +# Endpoint Service Integration-side parameters +# Listener port required to be opened for RPC Server, default: 6010 +endpoint.listener.port=6010 + + +####################################################################################################### +# # +# timestamp Service config # +# # +####################################################################################################### +# Timestamp Service Parameters +wesign.accessTokenUrl= +wesign.signTicketUrl= +wesign.timestampUrl= +wesign.appId= +wesign.secret= \ No newline at end of file diff --git a/src/test/java/com/webank/weid/BaseTest.java b/src/test/java/com/webank/weid/BaseTest.java index 6c75ef7c..f4b12ace 100644 --- a/src/test/java/com/webank/weid/BaseTest.java +++ b/src/test/java/com/webank/weid/BaseTest.java @@ -1,104 +1,80 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid; import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.rpc.AuthorityIssuerService; -import com.webank.weid.rpc.CptService; -import com.webank.weid.rpc.CredentialService; -import com.webank.weid.rpc.WeIdService; -import com.webank.weid.service.BaseService; -import java.math.BigInteger; -import org.bcos.contract.tools.ToolConf; +import com.webank.weid.service.impl.*; +import com.webank.weid.service.rpc.*; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Test base class. - * + * * @author v_wbgyang */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration( - locations = {"classpath:SpringApplicationContext-test.xml", "classpath:applicationContext.xml"}) -public abstract class BaseTest extends BaseService { +public abstract class BaseTest { - @Autowired protected AuthorityIssuerService authorityIssuerService; - - @Autowired protected CptService cptService; - - @Autowired protected WeIdService weIdService; - - @Autowired protected CredentialService credentialService; + protected CredentialPojoService credentialPojoService; + protected EvidenceService evidenceService; + protected PolicyService policyService; - @Autowired - protected ToolConf toolConf; + /** + * the private key of sdk is a BigInteger,which needs to be used when registering authority. + */ + protected String privateKey; + + static { + // mock DB + //MockMysqlDriver.mockMysqlDriver(); + MockIssuerClient.mockMakeCredentialTemplate(); + } /** - * initialization some for test. - * - * @throws Exception may be throw Exception + * initialization some for test. */ @Before - public void setUp() throws Exception { + public void setUp() { + + authorityIssuerService = new AuthorityIssuerServiceImpl(); + cptService = new CptServiceImpl(); + weIdService = new WeIdServiceImpl(); + credentialService = new CredentialServiceImpl(); + evidenceService = new EvidenceServiceImpl(); + credentialPojoService = new CredentialPojoServiceImpl(); + policyService = new PolicyServiceImpl(); - TestBaseUtil.privKey = new BigInteger(toolConf.getPrivKey(), 16).toString(); + privateKey = TestBaseUtil.readPrivateKeyFromFile("private_key"); testInit(); } /** - * tearDown some for test. - * - * @throws Exception may be throw Exception + * tearDown some for test. */ @After - public void tearDown() throws Exception { + public void tearDown() { authorityIssuerService = null; cptService = null; weIdService = null; credentialService = null; - toolConf = null; + evidenceService = null; + credentialPojoService = null; testFinalize(); } - public void testInit() throws Exception { + public void testInit() { Assert.assertTrue(true); } - public void testFinalize() throws Exception { + public void testFinalize() { Assert.assertTrue(true); } - - public int getBlockNumber() throws Exception { - return super.getWeb3j().ethBlockNumber().send().getBlockNumber().intValue(); - } -} +} \ No newline at end of file diff --git a/src/test/java/com/webank/weid/MockIssuerClient.java b/src/test/java/com/webank/weid/MockIssuerClient.java new file mode 100644 index 00000000..17454bbe --- /dev/null +++ b/src/test/java/com/webank/weid/MockIssuerClient.java @@ -0,0 +1,35 @@ + + +package com.webank.weid; + +import java.util.List; + +import com.webank.wedpr.selectivedisclosure.CredentialTemplateEntity; +import com.webank.wedpr.selectivedisclosure.IssuerClient; +import com.webank.wedpr.selectivedisclosure.IssuerResult; +import com.webank.wedpr.selectivedisclosure.proto.TemplatePublicKey; +import mockit.Mock; +import mockit.MockUp; + +public abstract class MockIssuerClient { + + /** + * mock the makeCredentialTemplate for CPT. + */ + public static void mockMakeCredentialTemplate() { + + new MockUp() { + + @Mock + public IssuerResult makeCredentialTemplate(List list) { + IssuerResult restult = new IssuerResult(); + restult.templateSecretKey = "templateSecretKey"; + CredentialTemplateEntity template = new CredentialTemplateEntity(); + template.setCredentialKeyCorrectnessProof("credentialKeyCorrectnessProof"); + template.setPublicKey(TemplatePublicKey.getDefaultInstance()); + restult.credentialTemplateEntity = template; + return restult; + } + }; + } +} diff --git a/src/test/java/com/webank/weid/MockMysqlDriver.java b/src/test/java/com/webank/weid/MockMysqlDriver.java new file mode 100644 index 00000000..dde21a5d --- /dev/null +++ b/src/test/java/com/webank/weid/MockMysqlDriver.java @@ -0,0 +1,160 @@ + + +package com.webank.weid; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import mockit.Invocation; +import mockit.Mock; +import mockit.MockUp; +import org.apache.commons.collections4.CollectionUtils; + +import com.webank.weid.constant.DataDriverConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.mysql.SqlDomain; +import com.webank.weid.suite.persistence.mysql.SqlExecutor; + +public abstract class MockMysqlDriver { + + /** + * mock DB for storage data. + */ + public static final Map> mockDbMap = + new HashMap>(); + + /** + * the default method for mock mySqlDriver. + */ + public static void mockMysqlDriver() { + + new MockUp() { + + //SqlExecutor executor; + SqlDomain sqlDomain; + @Mock + public void $init(Invocation invocation, SqlDomain sqlDomain) { + //this.executor = invocation.getInvokedInstance(); + //Deencapsulation + this.sqlDomain = sqlDomain; + } + + @Mock + public ResponseData execute(String sql, Object... data) { + String tableDomain = sqlDomain.getTableName(); + Map dbMap = mockDbMap.get(tableDomain); + if (sql.startsWith("insert")) { + if (!mockDbMap.containsKey(tableDomain)) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + if (dbMap.containsKey(data[0].toString())) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + dbMap.put(data[0].toString(), data[1]); + } else if (sql.startsWith("delete")) { + if (!mockDbMap.containsKey(tableDomain)) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + if (!dbMap.containsKey(data[0].toString())) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.SUCCESS + ); + } + dbMap.remove(data[0].toString()); + } else if (sql.startsWith("update")) { + if (!mockDbMap.containsKey(tableDomain)) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + if (!dbMap.containsKey(data[3].toString())) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.SUCCESS + ); + } + dbMap.put(data[3].toString(), data[1]); + } else if (sql.startsWith("CREATE")) { + if (mockDbMap.containsKey(tableDomain)) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } + if (!mockDbMap.containsKey(tableDomain)) { + mockDbMap.put(tableDomain, new HashMap()); + } + } + return new ResponseData(1, ErrorCode.SUCCESS); + } + + @Mock + public ResponseData> executeQuery(String sql, Object... data) { + String tableName = sqlDomain.getTableName(); + Map map = new HashMap(); + if (mockDbMap.containsKey(tableName)) { + if (data != null && data.length > 0) { + map.put(DataDriverConstant.SQL_COLUMN_DATA, + (String)mockDbMap.get(tableName).get(data[0])); + return new ResponseData>(map, ErrorCode.SUCCESS); + } + map.put(DataDriverConstant.SQL_COLUMN_DATA, tableName); + return new ResponseData>(map, ErrorCode.SUCCESS); + } + return new ResponseData>(null, + ErrorCode.PERSISTENCE_EXECUTE_FAILED); + } + + @Mock + public ResponseData batchAdd(String sql, List> dataList) { + System.out.println("mock..........."); + String tableName = sqlDomain.getTableName(); + List values = dataList.get(dataList.size() - 1); + for (List list : dataList) { + if (CollectionUtils.isEmpty(list) || list.size() != values.size()) { + return + new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_BATCH_ADD_DATA_MISMATCH + ); + } + } + List idList = dataList.get(0); + int saveCount = 0; + for (int i = 0; i < idList.size(); i++) { + if (mockDbMap.get(tableName).containsKey(idList.get(i))) { + return new ResponseData( + DataDriverConstant.SQL_EXECUTE_FAILED_STATUS, + ErrorCode.PERSISTENCE_EXECUTE_FAILED + ); + } else { + mockDbMap.get(tableName) + .put(idList.get(i).toString(), dataList.get(1).get(i).toString()); + saveCount++; + } + } + return new ResponseData(saveCount, ErrorCode.SUCCESS); + } + + @Mock + public void resolveTableDomain(String checkTableSql, String createTableSql) { + if (!mockDbMap.containsKey(sqlDomain.getTableName())) { + mockDbMap.put(sqlDomain.getTableName(), new HashMap()); + } + } + }; + } +} diff --git a/src/test/java/com/webank/weid/common/BaseBean.java b/src/test/java/com/webank/weid/common/BaseBean.java deleted file mode 100644 index fc9fbf4a..00000000 --- a/src/test/java/com/webank/weid/common/BaseBean.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.common; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.Map; - -/** - * debug class for output object information. - * @author v_wbgyang - * - */ -public class BaseBean { - - public static SimpleDateFormat getFormat() { - return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - } - - /** - * printSimpe Bean. - * @param obj required - */ - public static void printSimpleBean(Object obj) { - Field[] f = obj.getClass().getDeclaredFields(); - for (int i = 0; (f != null) && (i < f.length); i++) { - try { - if (f[i].getModifiers() == 2) { - Method m = obj.getClass().getMethod("get" - + f[i].getName().substring(0, 1).toUpperCase() - + f[i].getName().substring(1), new Class[0]); - if (m != null) { - System.out.println(f[i].getName() + ": " + m.invoke(obj, new Object[] {})); - } - } - } catch (NoSuchMethodException ex) { - System.out.println("no attribute:" + f[i].getName() + " to match for the method"); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - /** - * printSimple Collection. - * @param c this is object of Collection - */ - public static void printSimpleCollection(Collection c) { - if (c == null) { - return; - } - Iterator it = c.iterator(); - int i = 0; - while (it.hasNext()) { - System.out.println("[" + i++ + "]"); - printSimpleBean(it.next()); - } - } - - /** - * printSimple Map. - * @param map this is map - */ - public static void printSimpleMap(Map map) { - if (map == null) { - return; - } - Iterator it = map.keySet().iterator(); - while (it.hasNext()) { - Object obj = it.next(); - if ((obj instanceof Date)) { - System.out.println(getFormat().format((Date) obj) + ": " + map.get(obj)); - } else { - System.out.println(obj + ": " + map.get(obj)); - } - } - } - - private static void printBean(String blank, Object obj) { - if (isPrimitive(obj)) { - System.out.println(blank + obj); - return; - } - if ((obj instanceof Date)) { - System.out.println(blank + getFormat().format(obj)); - return; - } - if ((obj instanceof String[])) { - String[] a = (String[]) obj; - for (int i = 0; i < a.length; i++) { - System.out.println("[" + i + "]" + ": " + a[i]); - } - } - Field[] f = obj.getClass().getDeclaredFields(); - for (int i = 0; (f != null) && (i < f.length); i++) { - try { - if (f[i].getModifiers() == 2) { - Method m = obj.getClass().getMethod("get" - + f[i].getName().substring(0, 1).toUpperCase() - + f[i].getName().substring(1), new Class[0]); - - if (m != null) { - Object left = f[i].getName(); - Object right = m.invoke(obj, new Object[] {}); - printByType(blank, left, right); - } - } - } catch (NoSuchMethodException ex) { - System.out.println( - blank + " no attribute:" + f[i].getName() + " to match for the method"); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private static void printCollection(String blank, Collection c) { - if (c == null) { - return; - } - Iterator it = c.iterator(); - int i = 0; - while (it.hasNext()) { - Object obj = it.next(); - if (isPrimitive(obj)) { - System.out.println(blank + "[" + i++ + "]: " + obj); - } else if ((obj instanceof Date)) { - System.out.println(blank + "[" + i++ + "]: " + getFormat().format(obj)); - } else { - System.out.println(blank + "[" + i++ + "]: " + obj.getClass().getName()); - print(blank + " ", obj); - } - } - } - - private static void printMap(String blank, Map map) { - if (map == null) { - return; - } - Iterator it = map.keySet().iterator(); - while (it.hasNext()) { - Object left = it.next(); - Object right = map.get(left); - printByType(blank, left, right); - } - } - - protected static boolean isPrimitive(Object obj) { - if (obj == null) { - return false; - } - if (((obj instanceof Integer)) - || ((obj instanceof Boolean)) - || ((obj instanceof Character)) - || ((obj instanceof Byte)) - || ((obj instanceof Short)) - || ((obj instanceof Long)) - || ((obj instanceof Float)) - || ((obj instanceof Double)) - || ((obj instanceof Void)) - || ((obj instanceof String)) - || ((obj instanceof BigDecimal)) - || ((obj instanceof BigInteger)) - || (obj == null)) { - return true; - } - return false; - } - - private static void printByType(String blank, Object left, Object right) { - if (right == null) { - System.out.println(blank + left + ": null"); - return; - } - if ((left != null) && ((left instanceof Date))) { - left = getFormat().format((Date) left); - } - Class clazz = right.getClass(); - if (isPrimitive(right)) { - System.out.println(blank + left + ": " + right); - } else if ((right instanceof Date)) { - System.out.println(blank + left + ": " + getFormat().format(right)); - } else if ((right instanceof Collection)) { - System.out.println(blank + left + ":(" + clazz.getName() + ")"); - printCollection(blank + " ", (Collection) right); - } else if ((right instanceof Map)) { - System.out.println(blank + left + ":(" + clazz.getName() + ")"); - printMap(blank + " ", (Map) right); - } else { - System.out.println(blank + left + ":(" + clazz.getName() + ")"); - printBean(blank + " ", right); - } - } - - private static void print(String blank, Object obj) { - if (obj == null) { - return; - } - if ((obj instanceof Collection)) { - printCollection(blank, (Collection) obj); - } else if ((obj instanceof Map)) { - printMap(blank, (Map) obj); - } else { - printBean(blank, obj); - } - } - - /** - * print object. - * @param obj this object for print - */ - public static void print(Object obj) { - if (obj == null) { - return; - } - if ((obj instanceof Collection)) { - printCollection("", (Collection) obj); - } else if ((obj instanceof Map)) { - printMap("", (Map) obj); - } else { - printBean("", obj); - } - } -} diff --git a/src/test/java/com/webank/weid/common/BeanConstant.java b/src/test/java/com/webank/weid/common/BeanConstant.java new file mode 100644 index 00000000..19fd39a5 --- /dev/null +++ b/src/test/java/com/webank/weid/common/BeanConstant.java @@ -0,0 +1,51 @@ + + +package com.webank.weid.common; + +/** + * the constant for BaseBean to get Object String. + * + * @author v_wbgyang + */ +public class BeanConstant { + + /** + * line separator. + */ + public static final String LINE_CHARAC = System.lineSeparator(); + + /** + * left square bracket. + */ + public static final String LEFT_MID_BRACKETS = "["; + + /** + * right square bracket. + */ + public static final String RIGHT_MID_BRACKETS = "]"; + + /** + * colon. + */ + public static final String COLON_CHARAC = ":"; + + /** + * left parenthesis. + */ + public static final String LEFT_BRACKETS = "("; + + /** + * right parenthesis. + */ + public static final String RIGHT_BRACKETS = ")"; + + /** + * blank space. + */ + public static final String BLANK_SPACE = " "; + + /** + * empty object. + */ + public static final String BLANK_STR = "null"; +} diff --git a/src/test/java/com/webank/weid/common/BeanUtil.java b/src/test/java/com/webank/weid/common/BeanUtil.java index b06840a4..d47d0736 100644 --- a/src/test/java/com/webank/weid/common/BeanUtil.java +++ b/src/test/java/com/webank/weid/common/BeanUtil.java @@ -1,139 +1,277 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.common; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.Map; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Object util. + * debug class for output object information. * * @author v_wbgyang */ -public class BeanUtil extends BaseBean { +public class BeanUtil { - /** - * print Object with log. - */ - public static void print(Object obj) { - BaseBean.print(obj); + private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtil.class); + + private static final Set> primitiveWrapperTypeSet = new HashSet<>(); + + static { + primitiveWrapperTypeSet.add(Boolean.class); + primitiveWrapperTypeSet.add(Byte.class); + primitiveWrapperTypeSet.add(Character.class); + primitiveWrapperTypeSet.add(Double.class); + primitiveWrapperTypeSet.add(Float.class); + primitiveWrapperTypeSet.add(Integer.class); + primitiveWrapperTypeSet.add(Long.class); + primitiveWrapperTypeSet.add(Short.class); + primitiveWrapperTypeSet.add(boolean[].class); + primitiveWrapperTypeSet.add(byte[].class); + primitiveWrapperTypeSet.add(char[].class); + primitiveWrapperTypeSet.add(double[].class); + primitiveWrapperTypeSet.add(float[].class); + primitiveWrapperTypeSet.add(int[].class); + primitiveWrapperTypeSet.add(long[].class); + primitiveWrapperTypeSet.add(short[].class); } - /** - * check whether the two objects are the same. - */ - public static boolean equals(Object left, Object right) { - // if obj1 == obj2 then return true - if (left == right) { - return true; - } + private static SimpleDateFormat getFormat() { + return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + } - // if obj1 or obj2 is null then return false - if (left == null || right == null) { - return false; + private static void beanToString(String blank, Object obj, StringBuilder beanStr) { + if (isSimpleValueType(obj)) { + beanStr.append(blank) + .append(String.valueOf(obj)) + .append(BeanConstant.LINE_CHARAC); + return; } - - if (left.getClass() != right.getClass()) { - return false; + if ((obj instanceof Date)) { + beanStr.append(blank) + .append(getFormat().format(obj)) + .append(BeanConstant.LINE_CHARAC); + return; } - - try { - if ((left instanceof Collection)) { - return equalsCollection((Collection) left, (Collection) right); + if ((obj instanceof String[])) { + String[] a = (String[]) obj; + for (int i = 0; i < a.length; i++) { + beanStr.append(BeanConstant.LEFT_MID_BRACKETS) + .append(i) + .append(BeanConstant.RIGHT_MID_BRACKETS) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.BLANK_SPACE) + .append(a[i]) + .append(BeanConstant.LINE_CHARAC); } - if ((left instanceof Map)) { - return equalsMap((Map) left, (Map) right); + } + Field[] f = obj.getClass().getDeclaredFields(); + for (int i = 0; i < f.length; i++) { + try { + if (f[i].getModifiers() == Modifier.PRIVATE) { + Method m = obj.getClass().getMethod("get" + + f[i].getName().substring(0, 1).toUpperCase(Locale.getDefault()) + + f[i].getName().substring(1), new Class[0]); + Object left = f[i].getName(); + Object right = m.invoke(obj, new Object[]{}); + formatByType(blank, left, right, beanStr); + } + } catch (NoSuchMethodException ex) { + beanStr.append(blank) + .append(" no attribute:") + .append(f[i].getName()) + .append(" to match for the method") + .append(BeanConstant.LINE_CHARAC); + } catch (IllegalAccessException e) { + LOGGER.error("printBean error:", e); + } catch (IllegalArgumentException e) { + LOGGER.error("printBean error:", e); + } catch (InvocationTargetException e) { + LOGGER.error("printBean error:", e); } - return equalsObject(left, right); + } + } - } catch (Exception e) { - throw new RuntimeException(e); + private static void collectionToString(String blank, Collection c, StringBuilder beanStr) { + if (c == null) { + return; + } + Iterator it = c.iterator(); + int i = 0; + while (it.hasNext()) { + Object obj = it.next(); + if (obj == null) { + beanStr.append(blank) + .append(BeanConstant.LEFT_MID_BRACKETS) + .append(i++) + .append(BeanConstant.RIGHT_MID_BRACKETS) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.BLANK_STR) + .append(BeanConstant.LINE_CHARAC); + continue; + } + if (isSimpleValueType(obj)) { + beanStr.append(blank) + .append(BeanConstant.LEFT_MID_BRACKETS) + .append(i++) + .append(BeanConstant.RIGHT_MID_BRACKETS) + .append(BeanConstant.COLON_CHARAC) + .append(obj) + .append(BeanConstant.LINE_CHARAC); + } else if ((obj instanceof Date)) { + beanStr.append(blank) + .append(BeanConstant.LEFT_MID_BRACKETS) + .append(i++) + .append(BeanConstant.RIGHT_MID_BRACKETS) + .append(BeanConstant.COLON_CHARAC) + .append(getFormat().format(obj)) + .append(BeanConstant.LINE_CHARAC); + } else { + beanStr.append(blank) + .append(BeanConstant.LEFT_MID_BRACKETS) + .append(i++) + .append(BeanConstant.RIGHT_MID_BRACKETS) + .append(BeanConstant.COLON_CHARAC) + .append(obj.getClass().getName()) + .append(BeanConstant.LINE_CHARAC); + print(blank + " ", obj, beanStr); + } } } - private static boolean equalsObject(Object left, Object right) { - if (isPrimitive(left) || (left instanceof Date)) { - return left.equals(right); + private static void mapToString(String blank, Map map, StringBuilder beanStr) { + if (map == null) { + return; + } + for (Entry entry : map.entrySet()) { + Object left = entry.getKey(); + Object right = entry.getValue(); + formatByType(blank, left, right, beanStr); } + } - if ((left instanceof String[])) { - return Arrays.equals((String[]) left, (String[]) right); + private static boolean isSimpleValueType(Object obj) { + Class clazz = obj.getClass(); + if (obj == null) { + return false; + } + if (Date.class.isAssignableFrom(clazz)) { + return false; } + //return (ClassUtils.isPrimitiveOrWrapper(clazz) + return (clazz.isPrimitive() + || primitiveWrapperTypeSet.contains(clazz) + || Enum.class.isAssignableFrom(clazz) + || CharSequence.class.isAssignableFrom(clazz) + || Number.class.isAssignableFrom(clazz) + || Date.class.isAssignableFrom(clazz) + || URI.class == clazz || URL.class == clazz + || Locale.class == clazz || Class.class == clazz); + } - Field[] fieldLeft = left.getClass().getDeclaredFields(); - Class clsR = right.getClass(); - for (int i = 0; (fieldLeft != null) && (i < fieldLeft.length); i++) { - try { - Field fieldL = fieldLeft[i]; - Field fieldR = clsR.getDeclaredField(fieldL.getName()); - if (fieldL.getType() != fieldR.getType()) { - return false; - } - fieldL.setAccessible(true); - fieldR.setAccessible(true); - Object fieldLValue = fieldL.get(left); - Object fieldRValue = fieldR.get(right); - if (!equals(fieldLValue, fieldRValue)) { - return false; - } - } catch (Exception e) { - e.printStackTrace(); - } + private static void formatByType( + String blank, + Object left, + Object right, + StringBuilder beanStr) { + + Object leftObj = left; + if (right == null) { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.BLANK_STR) + .append(BeanConstant.LINE_CHARAC); + return; + } + if ((leftObj != null) && ((leftObj instanceof Date))) { + leftObj = getFormat().format((Date) leftObj); + } + Class clazz = right.getClass(); + if (isSimpleValueType(right)) { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.BLANK_SPACE) + .append(String.valueOf(right)) + .append(BeanConstant.LINE_CHARAC); + } else if ((right instanceof Date)) { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.BLANK_SPACE) + .append(getFormat().format(right)) + .append(BeanConstant.LINE_CHARAC); + } else if ((right instanceof Collection)) { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.LEFT_BRACKETS) + .append(clazz.getName()) + .append(BeanConstant.RIGHT_BRACKETS) + .append(BeanConstant.LINE_CHARAC); + collectionToString(blank + " ", (Collection) right, beanStr); + } else if ((right instanceof Map)) { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.LEFT_BRACKETS) + .append(clazz.getName()) + .append(BeanConstant.RIGHT_BRACKETS) + .append(BeanConstant.LINE_CHARAC); + mapToString(blank + " ", (Map) right, beanStr); + } else { + beanStr.append(blank) + .append(String.valueOf(leftObj)) + .append(BeanConstant.COLON_CHARAC) + .append(BeanConstant.LEFT_BRACKETS) + .append(clazz.getName()) + .append(BeanConstant.RIGHT_BRACKETS) + .append(BeanConstant.LINE_CHARAC); + beanToString(blank + " ", right, beanStr); } - return true; } - private static boolean equalsMap(Map left, Map right) throws Exception { - if (right.size() != left.size()) { - return false; + private static void print(String blank, Object obj, StringBuilder beanStr) { + if (obj == null) { + return; } - Iterator itL = right.keySet().iterator(); - Iterator itR = left.keySet().iterator(); - while (itL.hasNext()) { - Object leftObj = left.get(itL.next()); - Object rightObj = right.get(itR.next()); - if (!equals(leftObj, rightObj)) { - return false; - } + if ((obj instanceof Collection)) { + collectionToString(blank, (Collection) obj, beanStr); + } else if ((obj instanceof Map)) { + mapToString(blank, (Map) obj, beanStr); + } else { + beanToString(blank, obj, beanStr); } - return true; } - private static boolean equalsCollection(Collection left, Collection right) - throws Exception { - if (left.size() != right.size()) { - return false; + /** + * converting objects into strings. + * + * @param obj objects requiring format conversion + */ + public static String objToString(Object obj) { + StringBuilder beanStr = new StringBuilder(); + if (obj == null) { + return StringUtils.EMPTY; } - Iterator itL = left.iterator(); - Iterator itR = right.iterator(); - while (itL.hasNext()) { - Object leftObj = itL.next(); - Object rightObj = itR.next(); - if (!equals(leftObj, rightObj)) { - return false; - } + if ((obj instanceof Collection)) { + collectionToString("", (Collection) obj, beanStr); + } else if ((obj instanceof Map)) { + mapToString("", (Map) obj, beanStr); + } else { + beanToString("", obj, beanStr); } - return true; + return beanStr.toString(); } } diff --git a/src/test/java/com/webank/weid/common/LogUtil.java b/src/test/java/com/webank/weid/common/LogUtil.java new file mode 100644 index 00000000..73821308 --- /dev/null +++ b/src/test/java/com/webank/weid/common/LogUtil.java @@ -0,0 +1,38 @@ + + +package com.webank.weid.common; + +import org.slf4j.Logger; + +/** + * logging tool class. + * + * @author v_wbgyang + */ +public class LogUtil { + + /** + * log record. + * + * @param message log description + * @param obj objects to be recorded + */ + public static void info(Logger logger, String message, Object obj) { + logger.info( + "{}-{} result:\r\n{}", + stackTrace().getMethodName(), + message, + BeanUtil.objToString(obj) + ); + } + + /** + * get stack information for log records. + * + * @return StackTraceElement for currentThread. + */ + private static StackTraceElement stackTrace() { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + return stackTrace[3]; + } +} diff --git a/src/test/java/com/webank/weid/common/PasswordKey.java b/src/test/java/com/webank/weid/common/PasswordKey.java new file mode 100644 index 00000000..1d272b45 --- /dev/null +++ b/src/test/java/com/webank/weid/common/PasswordKey.java @@ -0,0 +1,37 @@ + + +package com.webank.weid.common; + +/** + * public and private key object class. + * + * @author v_wbgyang + */ +public class PasswordKey { + + /** + * the key of privateKey. + */ + private String privateKey; + + /** + * the key of publicKey. + */ + private String publicKey; + + public String getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + + public String getPublicKey() { + return publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } +} diff --git a/src/test/java/com/webank/weid/full/TestBaseServcie.java b/src/test/java/com/webank/weid/full/TestBaseServcie.java deleted file mode 100644 index d1d884d4..00000000 --- a/src/test/java/com/webank/weid/full/TestBaseServcie.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.full; - -import com.webank.weid.BaseTest; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.base.WeIdPublicKey; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.util.WeIdUtils; -import java.util.ArrayList; -import java.util.List; -import org.junit.Assert; - -/** - * testing basic method classes. - * - * @author v_wbgyang - * - */ -public abstract class TestBaseServcie extends BaseTest { - - protected static List issuerPrivateList = new ArrayList(); - - protected static boolean isInitIssuer = false; - - protected static CreateWeIdDataResult createWeId = null; - - protected static CreateWeIdDataResult createWeIdNew = null; - - protected static CreateWeIdDataResult createWeIdForGetDoc = null; - - protected static CreateWeIdDataResult createWeIdWithSetAttr = null; - - protected static CreateCredentialArgs createCredentialArgs = null; - - protected static RegisterCptArgs registerCptArgs = null; - - protected static CptBaseInfo cptBaseInfo = null; - - /** - * initializing related services. - */ - @Override - public void testInit() throws Exception { - - if (!isInitIssuer) { - try { - issuerPrivateList.add(TestBaseUtil.privKey); - initIssuer("org1.txt"); - isInitIssuer = true; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - if (createWeId == null) { - createWeId = this.createWeId(); - } - if (createWeIdWithSetAttr == null) { - createWeIdWithSetAttr = this.createWeIdWithSetAttr(); - } - if (createWeIdNew == null) { - createWeIdNew = this.createWeId(); - } - if (createWeIdForGetDoc == null) { - createWeIdForGetDoc = this.createWeIdWithSetAttr(); - } - } - - /** - * according to the analysis of the private key to create weIdentity DID,and - * registered as an authority, and its private key is recorded. - * - * @param fileName fileName - * @throws Exception may be throw Exception - */ - private void initIssuer(String fileName) throws Exception { - - String[] pk = TestBaseUtil.resolvePk(fileName); - - CreateWeIdArgs createWeIdArgs1 = TestBaseUtil.buildCreateWeIdArgs(); - createWeIdArgs1.setPublicKey(pk[0]); - createWeIdArgs1.getWeIdPrivateKey().setPrivateKey(pk[1]); - ResponseData response1 = weIdService.createWeId(createWeIdArgs1); - if (response1.getErrorCode().intValue() != ErrorCode.WEID_ALREADY_EXIST.getCode() - && response1.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { - throw new RuntimeException(response1.getErrorMessage()); - } - - String weId = WeIdUtils.convertPublicKeyToWeId(pk[0]); - - CreateWeIdDataResult createResult = new CreateWeIdDataResult(); - createResult.setWeId(weId); - createResult.setUserWeIdPrivateKey(new WeIdPrivateKey()); - createResult.setUserWeIdPublicKey(new WeIdPublicKey()); - createResult.getUserWeIdPrivateKey().setPrivateKey(pk[1]); - createResult.getUserWeIdPublicKey().setPublicKey(pk[0]); - - this.setPublicKey(createResult, pk[0], createResult.getWeId()); - this.setAuthentication(createResult, pk[0], createResult.getWeId()); - - CreateWeIdDataResult createWeId = new CreateWeIdDataResult(); - createWeId.setWeId(weId); - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); - - if (response.getErrorCode() - .intValue() != ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode() - && response.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { - throw new RuntimeException(response1.getErrorMessage()); - } - - issuerPrivateList.add(pk[1]); - System.out.println("initIssuer success"); - } - - /** - * verifyCredential. - * - * @param credential credential - * @return - */ - protected ResponseData verifyCredential(Credential credential) { - - ResponseData response = credentialService.verifyCredential(credential); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); - - return response; - } - - /** - * createCredential. - * - * @param createCredentialArgs createCredentialArgs - * @return - */ - protected Credential createCredential(CreateCredentialArgs createCredentialArgs) { - - ResponseData response = - credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); - - return response.getResult(); - } - - /** - * cpt register. - * - * @param createWeId createWeId - * @param registerCptArgs registerCptArgs - * @param isRegisterAuthorityIssuer isRegisterAuthorityIssuer - * @return - */ - protected CptBaseInfo registerCpt( - CreateWeIdDataResult createWeId, - RegisterCptArgs registerCptArgs) { - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); - - return response.getResult(); - } - - /** - * cpt register. - * - * @param createWeId createWeId - * @param isRegisterAuthorityIssuer isRegisterAuthorityIssuer - * @return - */ - protected CptBaseInfo registerCpt(CreateWeIdDataResult createWeId) { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - CptBaseInfo cptBaseInfo = registerCpt(createWeId, registerCptArgs); - - return cptBaseInfo; - } - - /** - * create weIdentity DID and registerAuthorityIssuer. - * - * @return CreateWeIdDataResult - * @throws Exception may be throw Exception - */ - protected CreateWeIdDataResult registerAuthorityIssuer() throws Exception { - - CreateWeIdDataResult createWeId = this.createWeId(); - - registerAuthorityIssuer(createWeId); - - return createWeId; - } - - /** - * registerAuthorityIssuer default. - */ - protected void registerAuthorityIssuer(CreateWeIdDataResult createWeId) { - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * create weIdentity DID and set Attribute default. - * - * @return CreateWeIdDataResult - */ - protected CreateWeIdDataResult createWeIdWithSetAttr() { - - CreateWeIdDataResult createWeId = this.createWeId(); - - try { - this.setPublicKey(createWeId, - createWeId.getUserWeIdPublicKey().getPublicKey(), - createWeId.getWeId()); - this.setAuthentication(createWeId, - createWeId.getUserWeIdPublicKey().getPublicKey(), - createWeId.getWeId()); - this.setService(createWeId, TestData.serviceType, TestData.serviceEndpoint); - } catch (Exception e) { - e.printStackTrace(); - Assert.assertEquals(false, true); - } - return createWeId; - } - - /** - * create weIdentity DID without set Attribute default. - * - * @return CreateWeIdDataResult - */ - protected CreateWeIdDataResult createWeId() { - - ResponseData createWeIdDataResult = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(createWeIdDataResult); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), - createWeIdDataResult.getErrorCode().intValue()); - Assert.assertNotNull(createWeIdDataResult.getResult()); - - return createWeIdDataResult.getResult(); - } - - /** - * setPublicKey default. - * - * @param createResult createResult - * @param publicKey publicKey - * @param owner owner - * @throws Exception Exception - */ - protected void setPublicKey(CreateWeIdDataResult createResult, String publicKey, String owner) - throws Exception { - - // setPublicKey for this WeId - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createResult); - setPublicKeyArgs.setPublicKey(publicKey); - setPublicKeyArgs.setOwner(owner); - - ResponseData responseSetPub = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(responseSetPub); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseSetPub.getErrorCode().intValue()); - Assert.assertEquals(true, responseSetPub.getResult()); - } - - /** - * setService default. - * - * @param createResult createResult - * @param serviceType serviceType - * @param serviceEnpoint serviceEnpoint - * @throws Exception may be throw Exception - */ - protected void setService( - CreateWeIdDataResult createResult, - String serviceType, - String serviceEnpoint) - throws Exception { - - // setService for this weIdentity DID - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createResult); - setServiceArgs.setType(serviceType); - setServiceArgs.setServiceEndpoint(serviceEnpoint); - - ResponseData responseSetSer = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(responseSetSer); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseSetSer.getErrorCode().intValue()); - Assert.assertEquals(true, responseSetSer.getResult()); - } - - /** - * setAuthenticate default. - * - * @param createResult createResult - * @param publicKey publicKey - * @param owner owner - * @throws Exception may be throw Exception - */ - protected void setAuthentication( - CreateWeIdDataResult createResult, - String publicKey, - String owner) - throws Exception { - - // setAuthenticate for this weIdentity DID - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createResult); - setAuthenticationArgs.setOwner(owner); - setAuthenticationArgs.setPublicKey(publicKey); - ResponseData responseSetAuth = - weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(responseSetAuth); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseSetAuth.getErrorCode().intValue()); - Assert.assertEquals(true, responseSetAuth.getResult()); - } -} diff --git a/src/test/java/com/webank/weid/full/TestBaseService.java b/src/test/java/com/webank/weid/full/TestBaseService.java new file mode 100644 index 00000000..40fb6a3c --- /dev/null +++ b/src/test/java/com/webank/weid/full/TestBaseService.java @@ -0,0 +1,681 @@ + + +package com.webank.weid.full; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.Multibase.Multibase; +import com.webank.weid.util.Multicodec.DecodedData; +import com.webank.weid.util.Multicodec.Multicodec; +import com.webank.weid.util.Multicodec.MulticodecEncoder; +import org.fisco.bcos.sdk.model.CryptoType; +import org.fisco.bcos.sdk.v3.codec.datatypes.StaticArray; +import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.BaseTest; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.CredentialWrapper; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CreateCredentialArgs; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.protocol.request.CreateWeIdArgs; +import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.CredentialUtils; +import com.webank.weid.util.WeIdUtils; + +/** + * testing basic method classes. + * + * @author v_wbgyang + */ +public abstract class TestBaseService extends BaseTest { + + /** + * log4j. + */ + private static final Logger logger = LoggerFactory.getLogger(TestBaseService.class); + + /** + * private key of authority membership list. + */ + public static volatile List issuerPrivateList = null; + + /** + * whether to initialize authority list. + */ + protected static volatile boolean isInitIssuer = false; + + /** + * weId information required for use cases. + */ + protected static volatile CreateWeIdDataResult createWeIdResult = null; + + /** + * new weId information required for use cases. + */ + protected static volatile CreateWeIdDataResult createWeIdNew = null; + + /** + * weId information and set related attribute. + */ + protected static volatile CreateWeIdDataResult createWeIdResultWithSetAttr = null; + + /** + * parameters needed to create credentials. + */ + protected static volatile CreateCredentialArgs createCredentialArgs = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgs = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgs1 = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgs2 = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgs3 = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgs4 = null; + + /** + * parameters needed to create credentialPojos. + */ + protected static volatile CreateCredentialPojoArgs> + createCredentialPojoArgsNew = null; + + /** + * CredentialPojo information required for use cases. selectiveCredential. + */ + protected static volatile CredentialPojo credentialPojo = null; + + /** + * selectiveCredentialPojo information required for use cases. + */ + protected static volatile CredentialPojo selectiveCredentialPojo = null; + + + /** + * parameters needed to register CPT. + */ + protected static volatile CptMapArgs registerCptArgs = null; + + /** + * parameters needed to register CPT. + */ + protected static volatile CptMapArgs registerCptArgs1 = null; + + /** + * parameters needed to register CPT. + */ + protected static volatile CptMapArgs registerCptArgs2 = null; + + /** + * parameters needed to register CPT. + */ + protected static volatile CptMapArgs registerCptArgs3 = null; + + /** + * parameters needed to register CPT. + */ + protected static volatile CptMapArgs registerCptArgs4 = null; + + /** + * CPT registration information. + */ + protected static volatile CptBaseInfo cptBaseInfo = null; + + /** + * CPT registration information. + */ + protected static volatile CptBaseInfo cptBaseInfo1 = null; + + /** + * CPT registration information. + */ + protected static volatile CptBaseInfo cptBaseInfo2 = null; + + /** + * CPT registration information. + */ + protected static volatile CptBaseInfo cptBaseInfo3 = null; + + /** + * CPT registration information. + */ + protected static volatile CptBaseInfo cptBaseInfo4 = null; + + /** + * initializing related services. + */ + @Override + public synchronized void testInit() { + + try { + issuerPrivateList = new ArrayList(); + issuerPrivateList.add(privateKey); + } catch (Exception e) { + logger.error("initIssuer error", e); + Assert.assertTrue(false); + } + + if (createWeIdResult == null) { + createWeIdResult = this.createWeId(); + } + if (createWeIdResultWithSetAttr == null) { + createWeIdResultWithSetAttr = this.createWeIdWithSetAttr(); + } + if (createWeIdNew == null) { + createWeIdNew = this.createWeId(); + } + if (createCredentialArgs == null) { + registerCptArgs = TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + cptBaseInfo = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + } + if (createCredentialPojoArgs == null) { + createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + CptBaseInfo cptBaseInfo = + this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + } + if (createCredentialPojoArgsNew == null) { + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeIdNew); + createCredentialPojoArgsNew = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdNew); + CptBaseInfo cptBaseInfo = this.registerCpt(createWeIdNew, registerCptArgs); + createCredentialPojoArgsNew.setCptId(cptBaseInfo.getCptId()); + } + if (credentialPojo == null) { + credentialPojo = this.createCredentialPojo(createCredentialPojoArgs); + } + if (selectiveCredentialPojo == null) { + selectiveCredentialPojo = this.createSelectiveCredentialPojo(credentialPojo); + } + } + + + /** + * test init for multilevel cpt. + */ + public synchronized void testInit4MlCpt() { + + try { + issuerPrivateList = new ArrayList(); + issuerPrivateList.add(privateKey); + } catch (Exception e) { + logger.error("initIssuer error", e); + Assert.assertTrue(false); + } + + if (createWeIdResult == null) { + createWeIdResult = this.createWeId(); + } + if (createWeIdResultWithSetAttr == null) { + createWeIdResultWithSetAttr = this.createWeIdWithSetAttr(); + } + if (createWeIdNew == null) { + createWeIdNew = this.createWeId(); + } + if (createCredentialPojoArgs1 == null) { + registerCptArgs1 = TestBaseUtil.buildCptArgs4MlCpt(createWeIdResultWithSetAttr); + createCredentialPojoArgs1 = + TestBaseUtil.buildCreateCredentialPojoArgs4MlCpt(createWeIdResultWithSetAttr); + cptBaseInfo1 = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs1); + createCredentialPojoArgs1.setCptId(cptBaseInfo1.getCptId()); + } + } + + + /** + * initializing related services,test init for multiple cpt. + */ + public synchronized void testInit4MultiCpt() { + + try { + issuerPrivateList = new ArrayList(); + issuerPrivateList.add(privateKey); + } catch (Exception e) { + logger.error("initIssuer error", e); + Assert.assertTrue(false); + } + + if (createWeIdResult == null) { + createWeIdResult = this.createWeId(); + } + if (createWeIdResultWithSetAttr == null) { + createWeIdResultWithSetAttr = this.createWeIdWithSetAttr(); + } + if (createWeIdNew == null) { + createWeIdNew = this.createWeId(); + } + if (createCredentialArgs == null) { + registerCptArgs = TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + cptBaseInfo = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + } + if (createCredentialPojoArgs2 == null) { + registerCptArgs2 = TestBaseUtil.buildCptArgs4MlCpt(createWeIdResultWithSetAttr); + createCredentialPojoArgs2 = + TestBaseUtil.buildCreateCredentialPojoArgs4MlCpt(createWeIdResultWithSetAttr); + cptBaseInfo2 = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs2); + createCredentialPojoArgs2.setCptId(cptBaseInfo2.getCptId()); + } + //support multiple CPT + if (createCredentialPojoArgs3 == null) { + registerCptArgs3 = TestBaseUtil.buildCptArgs4MultiCpt(createWeIdResultWithSetAttr); + createCredentialPojoArgs3 = + TestBaseUtil + .buildCreateCredentialPojoArgs4MultiCpt(createWeIdResultWithSetAttr); + cptBaseInfo3 = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs3); + createCredentialPojoArgs3.setCptId(cptBaseInfo3.getCptId()); + } + } + + /** + * test init for specify pdf template cpt. + */ + public synchronized void testInitSpecTplCpt() { + + try { + issuerPrivateList = new ArrayList(); + issuerPrivateList.add(privateKey); + } catch (Exception e) { + logger.error("initIssuer error", e); + Assert.assertTrue(false); + } + + if (createWeIdResult == null) { + createWeIdResult = this.createWeId(); + } + if (createWeIdResultWithSetAttr == null) { + createWeIdResultWithSetAttr = this.createWeIdWithSetAttr(); + } + if (createWeIdNew == null) { + createWeIdNew = this.createWeId(); + } + if (createCredentialPojoArgs4 == null) { + registerCptArgs4 = TestBaseUtil.buildCptArgs4SpecTplCpt(createWeIdResultWithSetAttr); + createCredentialPojoArgs4 = + TestBaseUtil.buildCreateCredentialPojoArgs4SpecTplCpt(createWeIdResultWithSetAttr); + cptBaseInfo4 = this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs4); + createCredentialPojoArgs4.setCptId(cptBaseInfo4.getCptId()); + } + } + + /** + * according to the analysis of the private key to create WeIdentity DID,and registered as an + * authority, and its private key is recorded. + * + * @param fileName fileName + */ + private void initIssuer(String fileName) { + + PasswordKey passwordKey = TestBaseUtil.resolvePk(fileName); + String publicKey = passwordKey.getPublicKey(); + String privateKey = passwordKey.getPrivateKey(); + + CreateWeIdArgs createWeIdArgs1 = TestBaseUtil.buildCreateWeIdArgs(); + createWeIdArgs1.setPublicKey(publicKey); + createWeIdArgs1.getWeIdPrivateKey().setPrivateKey(privateKey); + ResponseData response1 = weIdService.createWeId(createWeIdArgs1); + if (response1.getErrorCode().intValue() != ErrorCode.WEID_ALREADY_EXIST.getCode() + && response1.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + Assert.assertTrue(false); + } + + String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); + + CreateWeIdDataResult createResult = new CreateWeIdDataResult(); + createResult.setWeId(weId); + createResult.setUserWeIdPrivateKey(new WeIdPrivateKey()); + createResult.setUserWeIdPublicKey(new WeIdPublicKey()); + createResult.getUserWeIdPrivateKey().setPrivateKey(privateKey); + createResult.getUserWeIdPublicKey().setPublicKey(publicKey); + + this.setAuthentication(createResult, publicKey, createResult.getWeId()); + + CreateWeIdDataResult createWeId = new CreateWeIdDataResult(); + createWeId.setWeId(weId); + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, this.privateKey); + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + /*if (response.getErrorCode() + .intValue() != ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode() + && response.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { + Assert.assertTrue(false); + }*/ + + issuerPrivateList.add(privateKey); + logger.info("initIssuer success"); + } + + /** + * verifyCredential. + * + * @param credential credential + */ + protected ResponseData verifyCredential(Credential credential) { + + ResponseData response = credentialService.verify(credential); + return response; + } + + /** + * verifyCredentialPojo by issuer. + * + * @param credentialPojo credentialPojo + */ + protected ResponseData verifyCredentialPojo(CredentialPojo credentialPojo) { + + ResponseData response = credentialPojoService.verify( + credentialPojo.getIssuer(), credentialPojo); + return response; + } + + /** + * verifyCredentialPojo by weidpublic. + * + * @param credentialPojo credentialPojo + */ + protected ResponseData verifyCredentialPojo( + WeIdPublicKey weIdPublicKey, + CredentialPojo credentialPojo) { + + ResponseData response = credentialPojoService + .verify(weIdPublicKey, credentialPojo); + return response; + } + + /** + * createCredential. + * + * @param createCredentialArgs createCredentialArgs + */ + protected CredentialWrapper createCredential(CreateCredentialArgs createCredentialArgs) { + + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + return response.getResult(); + } + + /** + * createCredentialPojo. + */ + protected CredentialPojo createCredentialPojo( + CreateCredentialPojoArgs> createCredentialPojoArgs) { + + if (createCredentialPojoArgs == null) { + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + CptBaseInfo cptBaseInfo = + this.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + } + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + return response.getResult(); + } + + /** + * createSelectiveCredentialPojo. + */ + protected CredentialPojo createSelectiveCredentialPojo(CredentialPojo credentialPojo) { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + return response.getResult(); + } + + /** + * cpt register. + * + * @param createWeId createWeId + * @param registerCptArgs registerCptArgs + */ + protected CptBaseInfo registerCpt( + CreateWeIdDataResult createWeId, + CptMapArgs registerCptArgs) { + + ResponseData response = cptService.registerCpt(registerCptArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + return response.getResult(); + } + + /** + * cpt register. + * + * @param createWeId createWeId + */ + protected CptBaseInfo registerCpt(CreateWeIdDataResult createWeId) { + + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + + CptBaseInfo cptBaseInfo = registerCpt(createWeId, registerCptArgs); + + return cptBaseInfo; + } + + /** + * create WeIdentity DID and registerAuthorityIssuer. + * + * @return CreateWeIdDataResult + */ + protected CreateWeIdDataResult registerAuthorityIssuer() { + + CreateWeIdDataResult createWeId = this.createWeId(); + + registerAuthorityIssuer(createWeId); + + return createWeId; + } + + /** + * registerAuthorityIssuer default. + */ + protected void registerAuthorityIssuer(CreateWeIdDataResult createWeId) { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + logger.info("registerAuthorityIssuer result:"); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * register and return issuerType. + */ + public String registerIssuerType(String issuerType) { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeIdNew); + + ResponseData response + = authorityIssuerService.registerIssuerType(weIdAuthentication, issuerType); + LogUtil.info(logger, "registerIssuerType", response); + + return issuerType; + } + + /** + * create WeIdentity DID and set Attribute default. + * + * @return CreateWeIdDataResult + */ + protected CreateWeIdDataResult createWeIdWithSetAttr() { + + CreateWeIdDataResult createWeId = this.createWeId(); + + this.setAuthentication(createWeId, createWeId.getUserWeIdPublicKey().getPublicKey(), + createWeId.getWeId()); + this.setService(createWeId, TestData.SERVICE_TYPE, TestData.SERVICE_ENDPOINT); + return createWeId; + } + + /** + * create WeIdentity DID without set Attribute default. + * + * @return CreateWeIdDataResult + */ + protected CreateWeIdDataResult createWeId() { + + ResponseData createWeIdDataResult = weIdService.createWeId(); + LogUtil.info(logger, "createWeId", createWeIdDataResult); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + createWeIdDataResult.getErrorCode().intValue()); + Assert.assertNotNull(createWeIdDataResult.getResult()); + + return createWeIdDataResult.getResult(); + } + + /** + * setService default. + * + * @param createResult createResult + * @param serviceType serviceType + * @param serviceEnpoint serviceEnpoint + */ + protected void setService( + CreateWeIdDataResult createResult, + String serviceType, + String serviceEnpoint) { + + // setService for this WeIdentity DID + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createResult); + setServiceArgs.setType(serviceType); + setServiceArgs.setServiceEndpoint(serviceEnpoint); + + ResponseData responseSetSer = weIdService.setService(createResult.getWeId(), + setServiceArgs, createResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", responseSetSer); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseSetSer.getErrorCode().intValue()); + Assert.assertEquals(true, responseSetSer.getResult()); + } + + /** + * setAuthenticate default. + * + * @param createResult createResult + * @param publicKey publicKey + * @param owner owner + */ + protected void setAuthentication( + CreateWeIdDataResult createResult, + String publicKey, + String owner) { + + // setAuthenticate for this WeIdentity DID + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createResult); + setAuthenticationArgs.setController(owner); + setAuthenticationArgs.setPublicKey(publicKey); + ResponseData responseSetAuth = + weIdService.setAuthentication(createResult.getWeId(), setAuthenticationArgs, + createResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", responseSetAuth); + + Assert.assertEquals(ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS.getCode(), responseSetAuth.getErrorCode().intValue()); + Assert.assertEquals(false, responseSetAuth.getResult()); + } + + protected CredentialPojo copyCredentialPojo(CredentialPojo credentialPojo) { + return CredentialUtils.copyCredential(credentialPojo); + } + + protected CreateWeIdDataResult copyCreateWeId(CreateWeIdDataResult createWeId) { + CreateWeIdDataResult copyWeId = new CreateWeIdDataResult(); + copyWeId.setWeId(createWeId.getWeId()); + copyWeId.setUserWeIdPrivateKey(new WeIdPrivateKey()); + copyWeId.getUserWeIdPrivateKey() + .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); + copyWeId.setUserWeIdPublicKey(new WeIdPublicKey()); + copyWeId.getUserWeIdPublicKey() + .setPublicKey(createWeId.getUserWeIdPublicKey().getPublicKey()); + return copyWeId; + } +} diff --git a/src/test/java/com/webank/weid/full/TestBaseUtil.java b/src/test/java/com/webank/weid/full/TestBaseUtil.java index 6e9b9a4c..ee88b1e1 100644 --- a/src/test/java/com/webank/weid/full/TestBaseUtil.java +++ b/src/test/java/com/webank/weid/full/TestBaseUtil.java @@ -1,78 +1,45 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full; -import com.webank.weid.common.BeanUtil; +import com.fasterxml.jackson.databind.JsonNode; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.constant.JsonSchemaConstant; import com.webank.weid.protocol.base.AuthorityIssuer; import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.WeIdAuthentication; import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.base.WeIdPublicKey; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.request.UpdateCptArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; +import com.webank.weid.protocol.request.*; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Date; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; +import com.webank.weid.util.DataToolUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +import java.io.*; +import java.math.BigInteger; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * testing basic entity object building classes. - * @author v_wbgyang * + * @author v_wbgyang */ public class TestBaseUtil { /** - * the private key of sdk is a BigInteger,which needs to be used - * when registering authority. - * - */ - public static String privKey; - - /** - * build VerifyCredentialArgs. + * log4j. */ - public static VerifyCredentialArgs buildVerifyCredentialArgs( - Credential credential, - String publicKey) { - - VerifyCredentialArgs verifyCredentialArgs = new VerifyCredentialArgs(); - verifyCredentialArgs.setCredential(credential); - verifyCredentialArgs.setWeIdPublicKey(new WeIdPublicKey()); - verifyCredentialArgs.getWeIdPublicKey().setPublicKey(publicKey); - return verifyCredentialArgs; - } + private static final Logger logger = LoggerFactory.getLogger(TestBaseUtil.class); - /** + /** * build CreateCredentialArgs no cptId. */ public static CreateCredentialArgs buildCreateCredentialArgs(CreateWeIdDataResult createWeId) { @@ -83,13 +50,13 @@ public static CreateCredentialArgs buildCreateCredentialArgs(CreateWeIdDataResul createCredentialArgs.setWeIdPrivateKey(new WeIdPrivateKey()); createCredentialArgs.getWeIdPrivateKey() .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); - createCredentialArgs.setClaim(TestData.schemaData); + createCredentialArgs.setClaim(buildCptJsonSchemaData()); return createCredentialArgs; } - /** - * build default CreateCredentialArgs. + /** + * build default CreateCredentialArgs. */ public static CreateCredentialArgs buildCreateCredentialArgs( CreateWeIdDataResult createWeId, @@ -100,181 +67,697 @@ public static CreateCredentialArgs buildCreateCredentialArgs( return createCredentialArgs; } - /** - * build default UpdateCptArgs. + /** + * build CreateCredentialPojoArgs no cptId. + * + * @return CreateCredentialPojoArgs + */ + public static CreateCredentialPojoArgs> buildCreateCredentialPojoArgs( + CreateWeIdDataResult createWeId) { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs.setIssuer(createWeId.getWeId()); + createCredentialPojoArgs.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + createCredentialPojoArgs.setWeIdAuthentication(buildWeIdAuthentication(createWeId)); + try { + Map claimMap = buildCptJsonSchemaDataFromFile(); + claimMap.put("id", createWeId.getWeId()); + createCredentialPojoArgs.setClaim(claimMap); + + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + return null; + } + + return createCredentialPojoArgs; + } + + /** + * build CreateCredentialPojoArgs no cptId. + * + * @return CreateCredentialPojoArgs + */ + public static CreateCredentialPojoArgs> buildCreateCredentialPojoArgs4MlCpt( + CreateWeIdDataResult createWeId) { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs.setIssuer(createWeId.getWeId()); + createCredentialPojoArgs.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + createCredentialPojoArgs.setWeIdAuthentication(buildWeIdAuthentication(createWeId)); + try { + createCredentialPojoArgs.setClaim(buildCptJsonSchemaDataFromFile4MlCpt()); + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + return null; + } + + return createCredentialPojoArgs; + } + + /** + * build CreateCredentialPojoArgs no cptId. + * + * @return CreateCredentialPojoArgs + */ + public static CreateCredentialPojoArgs> + buildCreateCredentialPojoArgs4MultiCpt( + CreateWeIdDataResult createWeId) { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs.setIssuer(createWeId.getWeId()); + createCredentialPojoArgs.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + createCredentialPojoArgs.setWeIdAuthentication(buildWeIdAuthentication(createWeId)); + try { + createCredentialPojoArgs.setClaim(buildCptJsonSchemaDataFromFile4MultiCpt()); + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + return null; + } + + return createCredentialPojoArgs; + } + + /** + * build CreateCredentialPojoArgs no cptId. + * + * @return CreateCredentialPojoArgs + */ + public static CreateCredentialPojoArgs> + buildCreateCredentialPojoArgs4SpecTplCpt( + CreateWeIdDataResult createWeId) { + + CreateCredentialPojoArgs> createCredentialPojoArgs4 = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs4.setIssuer(createWeId.getWeId()); + createCredentialPojoArgs4.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + createCredentialPojoArgs4.setWeIdAuthentication(buildWeIdAuthentication(createWeId)); + try { + createCredentialPojoArgs4.setClaim(buildCptJsonSchemaDataFromFile4SpecTplCpt()); + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + return null; + } + + return createCredentialPojoArgs4; + } + + /** + * buildWeIdAuthentication. + * + * @param weIdData weId + * @return WeIdAuthentication + */ + public static WeIdAuthentication buildWeIdAuthentication(CreateWeIdDataResult weIdData) { + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(weIdData.getWeId()); + weIdAuthentication.setAuthenticationMethodId(weIdData.getWeId() + "#keys-0"); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey().setPrivateKey( + weIdData.getUserWeIdPrivateKey().getPrivateKey()); + return weIdAuthentication; + } + + /** + * build cpt json schemaData. + * + * @return HashMap + * @throws IOException IOException + */ + public static HashMap buildCptJsonSchemaDataFromFile() throws IOException { + + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + return cptJsonSchemaData; + } + + /** + * build cpt json schemaData. + * + * @return HashMap + * @throws IOException IOException + */ + public static HashMap buildCptJsonSchemaDataFromFile4MultiCpt() + throws IOException { + + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-singlelevel-claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + return cptJsonSchemaData; + } + + /** + * build cpt json schemaData. + * + * @return HashMap + * @throws IOException IOException + */ + public static HashMap buildCptJsonSchemaDataFromFile4MlCpt() + throws IOException { + + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-multilevel-claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + return cptJsonSchemaData; + } + + /** + * build cpt json schemaData. + * + * @return HashMap + * @throws IOException IOException + */ + public static HashMap buildCptJsonSchemaDataFromFile4SpecTplCpt() + throws IOException { + + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-spectpl-claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + return cptJsonSchemaData; + } + + /** + * build default CptMapArgs. + * + * @param createWeId WeId + * @return CptMapArgs + */ + public static CptMapArgs buildCptArgs(CreateWeIdDataResult createWeId) { + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(buildCptJsonSchema()); + cptMapArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + + return cptMapArgs; + } + + /** + * build MultiLevel CptMapArgs. + * + * @param createWeId WeId + * @return CptMapArgs + */ + public static CptMapArgs buildCptArgs4MlCpt(CreateWeIdDataResult createWeId) { + + //build cpt from file + CptStringArgs cptStringArgs = new CptStringArgs(); + try { + cptStringArgs = buildCptStringArgs4MlCpt(createWeId, true); + } catch (IOException e) { + logger.error("buildCptArgs4MlCpt failed. ", e); + } + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + cptMapArgs.setCptJsonSchema( + DataToolUtils.deserialize(cptStringArgs.getCptJsonSchema(), HashMap.class)); + + return cptMapArgs; + } + + /** + * build default CptMapArgs. + * + * @param createWeId WeId + * @return CptMapArgs */ - public static UpdateCptArgs buildUpdateCptArgs( + public static CptMapArgs buildCptArgs4MultiCpt(CreateWeIdDataResult createWeId) { + + //build cpt from file + CptStringArgs cptStringArgs = new CptStringArgs(); + try { + cptStringArgs = buildCptStringArgs4MultiCpt(createWeId, true); + } catch (IOException e) { + logger.error("buildCptArgs4MultiCpt failed. ", e); + } + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + cptMapArgs.setCptJsonSchema( + DataToolUtils.deserialize(cptStringArgs.getCptJsonSchema(), HashMap.class)); + + return cptMapArgs; + } + + /** + * build default CptMapArgs. + * + * @param createWeId WeId + * @return CptMapArgs + */ + public static CptMapArgs buildCptArgs4SpecTplCpt(CreateWeIdDataResult createWeId) { + + //build cpt from file + CptStringArgs cptStringArgs = new CptStringArgs(); + try { + cptStringArgs = buildCptStringArgs4SpecTplCpt(createWeId, true); + } catch (IOException e) { + logger.error("buildCptArgs4SpecTplCpt failed. ", e); + } + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + cptMapArgs.setCptJsonSchema( + DataToolUtils.deserialize(cptStringArgs.getCptJsonSchema(), HashMap.class)); + + return cptMapArgs; + } + + /** + * build default buildCptStringArgs. + */ + public static CptStringArgs buildCptStringArgs( CreateWeIdDataResult createWeId, - CptBaseInfo cptBaseInfo) { + Boolean isFormatFile) throws IOException { - UpdateCptArgs updateCptArgs = new UpdateCptArgs(); - updateCptArgs.setCptJsonSchema(TestData.schema); - updateCptArgs.setCptPublisher(createWeId.getWeId()); - updateCptArgs.setCptPublisherPrivateKey(new WeIdPrivateKey()); - updateCptArgs.getCptPublisherPrivateKey() - .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); - updateCptArgs.setCptId(cptBaseInfo.getCptId()); + String jsonSchema = TestData.SCHEMA; + if (isFormatFile) { + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("json-schema-cpt.json"); + jsonSchema = jsonNode.toString(); + } + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + return cptStringArgs; + } + + /** + * build MultiLevel buildCptStringArgs. + */ + public static CptStringArgs buildCptStringArgs4MlCpt( + CreateWeIdDataResult createWeId, + Boolean isFormatFile) throws IOException { + + String jsonSchema = TestData.SCHEMA; + if (isFormatFile) { + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-multilevel-cpt.json"); + jsonSchema = jsonNode.toString(); + } + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); - return updateCptArgs; + return cptStringArgs; } - /** - * build default RegisterCptArgs. + /** + * build MultiLevel buildCptStringArgs. */ - public static RegisterCptArgs buildRegisterCptArgs(CreateWeIdDataResult createWeId) { + public static CptStringArgs buildCptStringArgs4MultiCpt( + CreateWeIdDataResult createWeId, + Boolean isFormatFile) throws IOException { + + String jsonSchema = TestData.SCHEMA; + if (isFormatFile) { + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-singlelevel-cpt.json"); + jsonSchema = jsonNode.toString(); + } + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + + return cptStringArgs; + } - RegisterCptArgs registerCptArgs = new RegisterCptArgs(); - registerCptArgs.setCptJsonSchema(TestData.schema); - registerCptArgs.setCptPublisher(createWeId.getWeId()); - registerCptArgs.setCptPublisherPrivateKey(new WeIdPrivateKey()); - registerCptArgs.getCptPublisherPrivateKey() + /** + * build specify pdf template cpt. + */ + public static CptStringArgs buildCptStringArgs4SpecTplCpt( + CreateWeIdDataResult createWeId, + Boolean isFormatFile) throws IOException { + + String jsonSchema = TestData.SCHEMA; + if (isFormatFile) { + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("test-spectpl-cpt.json"); + jsonSchema = jsonNode.toString(); + } + + CptStringArgs cptStringArgs = new CptStringArgs(); + cptStringArgs.setCptJsonSchema(jsonSchema); + cptStringArgs.setWeIdAuthentication(buildWeIdAuthority(createWeId)); + + return cptStringArgs; + } + + /** + * build weId authority. + */ + public static WeIdAuthentication buildWeIdAuthority(CreateWeIdDataResult createWeId) { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeId.getWeId()); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey() .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); + return weIdAuthentication; + } + - return registerCptArgs; + /** + * build cpt json schema. + * + * @return HashMap + */ + public static HashMap buildCptJsonSchema() { + + HashMap cptJsonSchemaNew = new HashMap(3); + cptJsonSchemaNew.put(JsonSchemaConstant.TITLE_KEY, "Digital Identity"); + cptJsonSchemaNew.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = {"F", "M"}; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap propertitesMap4 = new HashMap(2); + propertitesMap4.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap4.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is weid"); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put("name", propertitesMap1); + cptJsonSchema.put("gender", propertitesMap2); + cptJsonSchema.put("age", propertitesMap3); + cptJsonSchema.put("id", propertitesMap4); + cptJsonSchemaNew.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchema); + + String[] genderRequired = {"id", "name", "gender"}; + cptJsonSchemaNew.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + return cptJsonSchemaNew; } - /** + /** + * build cpt json schemaData. + * + * @return HashMap + */ + public static HashMap buildCptJsonSchemaData() { + + HashMap cptJsonSchemaData = new HashMap(3); + cptJsonSchemaData.put("name", "zhang san"); + cptJsonSchemaData.put("gender", "F"); + cptJsonSchemaData.put("age", 18); + cptJsonSchemaData.put("id", "did:weid:101:0xe4bee5a07f282ffd3109699e21663cde0210fb64"); + return cptJsonSchemaData; + } + + /** * build default RegisterAuthorityIssuerArgs. + * + * @return RegisterAuthorityIssuerArgs */ public static RegisterAuthorityIssuerArgs buildRegisterAuthorityIssuerArgs( - CreateWeIdDataResult createWeId) { + CreateWeIdDataResult createWeId, + String privateKey) { - AuthorityIssuer authorityIssuer = new AuthorityIssuer(); - authorityIssuer.setWeId(createWeId.getWeId()); - authorityIssuer.setCreated(new Date().getTime()); - authorityIssuer.setName(TestData.authorityIssuerName); - authorityIssuer.setAccValue(TestData.authorityIssuerAccValue); + AuthorityIssuer authorityIssuer = new AuthorityIssuer( + createWeId.getWeId(), + TestData.AUTHORITY_ISSUER_NAME, + TestData.AUTHORITY_ISSUER_ACCVALUE, + null, + null, + null); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuer); registerAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(privKey); + registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(privateKey); return registerAuthorityIssuerArgs; } - /** + /** * build default CreateWeIdArgs. + * + * @return CreateWeIdArgs */ - public static CreateWeIdArgs buildCreateWeIdArgs() throws Exception { + public static CreateWeIdArgs buildCreateWeIdArgs() { CreateWeIdArgs args = new CreateWeIdArgs(); - String[] pk = createEcKeyPair(); - args.setPublicKey(pk[0]); + PasswordKey passwordKey = createEcKeyPair(); + args.setPublicKey(passwordKey.getPublicKey()); WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); - weIdPrivateKey.setPrivateKey(pk[1]); + weIdPrivateKey.setPrivateKey(passwordKey.getPrivateKey()); args.setWeIdPrivateKey(weIdPrivateKey); return args; } - /** + /** * buildSetPublicKeyArgs. + * + * @return SetAuthenticationArgs */ - public static SetAuthenticationArgs buildSetAuthenticationArgs(CreateWeIdDataResult createWeId) - throws Exception { + public static AuthenticationArgs buildSetAuthenticationArgs( + CreateWeIdDataResult createWeId) { - SetAuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); - setAuthenticationArgs.setWeId(createWeId.getWeId()); + AuthenticationArgs setAuthenticationArgs = new AuthenticationArgs(); setAuthenticationArgs.setPublicKey(createWeId.getUserWeIdPublicKey().getPublicKey()); - setAuthenticationArgs.setType(TestData.authenticationType); - setAuthenticationArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setAuthenticationArgs.getUserWeIdPrivateKey() - .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); return setAuthenticationArgs; } - /** - * buildSetPublicKeyArgs. - */ - public static SetPublicKeyArgs buildSetPublicKeyArgs(CreateWeIdDataResult createWeId) - throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = new SetPublicKeyArgs(); - setPublicKeyArgs.setWeId(createWeId.getWeId()); - setPublicKeyArgs.setPublicKey(createWeId.getUserWeIdPublicKey().getPublicKey()); - setPublicKeyArgs.setType(TestData.publicKeyType); - setPublicKeyArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setPublicKeyArgs.getUserWeIdPrivateKey() - .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); - - return setPublicKeyArgs; - } - - /** + /** * buildSetPublicKeyArgs. + * + * @param createWeId WeId + * @return SetServiceArgs */ - public static SetServiceArgs buildSetServiceArgs(CreateWeIdDataResult createWeId) - throws Exception { - - SetServiceArgs setServiceArgs = new SetServiceArgs(); - setServiceArgs.setWeId(createWeId.getWeId()); - setServiceArgs.setType(TestData.serviceType); - setServiceArgs.setServiceEndpoint(TestData.serviceEndpoint); - setServiceArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setServiceArgs.getUserWeIdPrivateKey() - .setPrivateKey(createWeId.getUserWeIdPrivateKey().getPrivateKey()); + public static ServiceArgs buildSetServiceArgs(CreateWeIdDataResult createWeId) { - return setServiceArgs; + ServiceArgs serviceArgs = new ServiceArgs(); + serviceArgs.setType(TestData.SERVICE_TYPE); + serviceArgs.setServiceEndpoint(TestData.SERVICE_ENDPOINT); + return serviceArgs; } - /** + /** * buildRemoveAuthorityIssuerArgs. + * + * @param createWeId WeId + * @param privateKey privateKey + * @return RemoveAuthorityIssuerArgs */ public static RemoveAuthorityIssuerArgs buildRemoveAuthorityIssuerArgs( - CreateWeIdDataResult createWeId) { + CreateWeIdDataResult createWeId, + String privateKey) { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = new RemoveAuthorityIssuerArgs(); removeAuthorityIssuerArgs.setWeId(createWeId.getWeId()); removeAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(privKey); + removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(privateKey); return removeAuthorityIssuerArgs; } - /** + /** * create a new public key - private key. + * + * @return PasswordKey */ - public static String[] createEcKeyPair() throws Exception { - ECKeyPair keyPair = Keys.createEcKeyPair(); - String publicKey = String.valueOf(keyPair.getPublicKey()); - String privateKey = String.valueOf(keyPair.getPrivateKey()); - String[] pk = new String[] {publicKey, privateKey}; - System.out.println(); - BeanUtil.print(pk); - return pk; + public static PasswordKey createEcKeyPair() { + + PasswordKey passwordKey = new PasswordKey(); + /*try { + ECKeyPair keyPair = DataToolUtils.createKeyPair(); + String publicKey = String.valueOf(keyPair.getPublicKey()); + String privateKey = String.valueOf(keyPair.getPrivateKey()); + passwordKey.setPrivateKey(privateKey); + passwordKey.setPublicKey(publicKey); + LogUtil.info(logger, "createEcKeyPair", passwordKey); + } catch (Exception e) { + logger.error("createEcKeyPair error:", e); + }*/ + String privateKey = DataToolUtils.generatePrivateKey(); + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey, 10)); + BigInteger bigPublicKey = + new BigInteger(publicKey, 10); + BigInteger bigPrivateKey =new BigInteger(privateKey, 10); + + //String publicKey = String.valueOf(bigPublicKey); + //String privateKey = String.valueOf(bigPrivateKey); + passwordKey.setPrivateKey(privateKey); + passwordKey.setPublicKey(publicKey); + LogUtil.info(logger, "createEcKeyPair", passwordKey); + return passwordKey; } /** - * to test the public and private key from the file. - * + * to test the public and private key from the file. + * * @param fileName fileName - * @return + * @return PasswordKey */ - public static String[] resolvePk(String fileName) { + public static PasswordKey resolvePk(String fileName) { + BufferedReader br = null; + FileInputStream fis = null; + InputStreamReader isr = null; + + PasswordKey passwordKey = new PasswordKey(); try { - String filePath = TestBaseUtil.class.getClassLoader().getResource(fileName).getFile(); - br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))); - String publicKey = br.readLine().split(":")[1]; // read publicKey - String privateKey = br.readLine().split(":")[1]; // read privateKey - System.out.println("publicKey:" + publicKey); - System.out.println("privateKey:" + privateKey); - return new String[] {publicKey, privateKey}; - } catch (Exception e) { - e.printStackTrace(); + URL fileUrl = TestBaseUtil.class.getClassLoader().getResource(fileName); + if (fileUrl == null) { + return passwordKey; + } + + String filePath = fileUrl.getFile(); + if (filePath == null) { + return passwordKey; + } + + fis = new FileInputStream(fileUrl.getFile()); + isr = new InputStreamReader(fis, StandardCharsets.UTF_8); + br = new BufferedReader(isr); + + List strList = new ArrayList(); + String line = null; + while ((line = br.readLine()) != null) { + strList.add(line); + } + + String[] pk = new String[2]; + for (int i = 0; i < strList.size(); i++) { + String str = strList.get(i); + if (StringUtils.isBlank(str)) { + continue; + } + String[] lineStr = str.split(":"); + + if (lineStr.length == 2) { + pk[i] = lineStr[1]; + } + } + passwordKey.setPublicKey(pk[0]); + passwordKey.setPrivateKey(pk[1]); + logger.info("publicKey:{}", passwordKey.getPublicKey()); + logger.info("privateKey:{}", passwordKey.getPrivateKey()); + return passwordKey; + } catch (FileNotFoundException e) { + logger.error("the file is not exists:", e); + } catch (IOException e) { + logger.error("resolvePk error:", e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { - e.printStackTrace(); + logger.error("BufferedReader close error:", e); + } + } + if (isr != null) { + try { + isr.close(); + } catch (IOException e) { + logger.error("InputStreamReader close error:", e); } } + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + logger.error("FileInputStream close error:", e); + } + } + } + return passwordKey; + } + + + /** + * Read key form file. + * + * @param fileName filename + * @return private key + */ + public static String readPrivateKeyFromFile(String fileName) { + + BufferedReader br = null; + FileInputStream fis = null; + InputStreamReader isr = null; + StringBuffer privateKey = new StringBuffer(); + + URL fileUrl = null; + try { + PathMatchingResourcePatternResolver resolver = + new PathMatchingResourcePatternResolver(); + fileUrl = resolver.getResource("classpath:" + fileName).getFile().toURL(); + } catch (IOException e) { + e.printStackTrace(); + } + // URL fileUrl = TestBaseUtil.class.getClassLoader().getResource(fileName); + if (fileUrl == null) { + return privateKey.toString(); + } + + String filePath = fileUrl.getFile(); + if (filePath == null) { + return privateKey.toString(); + } + + try { + fis = new FileInputStream(fileUrl.getFile()); + isr = new InputStreamReader(fis, StandardCharsets.UTF_8); + br = new BufferedReader(isr); + + String line = null; + while ((line = br.readLine()) != null) { + privateKey.append(line); + } + } catch (Exception e) { + logger.error("read privateKey from {} failed, error:{}", fileName, e); + } finally { + closeStream(br, fis, isr); + } + + return privateKey.toString(); + } + + private static void closeStream(BufferedReader br, FileInputStream fis, InputStreamReader isr) { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + logger.error("BufferedReader close error:", e); + } + } + if (isr != null) { + try { + isr.close(); + } catch (IOException e) { + logger.error("InputStreamReader close error:", e); + } + } + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + logger.error("FileInputStream close error:", e); + } } - return null; } } diff --git a/src/test/java/com/webank/weid/full/TestData.java b/src/test/java/com/webank/weid/full/TestData.java index a0d394ff..babe9cf7 100644 --- a/src/test/java/com/webank/weid/full/TestData.java +++ b/src/test/java/com/webank/weid/full/TestData.java @@ -1,81 +1,76 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify it under the terms of - * the GNU Lesser General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full; +import com.webank.weid.constant.WeIdConstant.PublicKeyType; + /** * The function of this class is to test the basic data required. - * - * @author v_wbgyang * + * @author v_wbgyang */ public class TestData { /** - * you may need to add public key after you create weIdentity DID,This property is the public + * you may need to add public key after you create WeIdentity DID,This property is the public * key type,but for now the value is fixed and you don't need to modify it. - * */ - public static String publicKeyType = "Secp256k1"; + public static final String PUBLIC_KEY_TYPE = PublicKeyType.ECDSA.getTypeName(); /** - * after you create weIdentity DID,you may need to add service information which indicates the + * after you create WeIdentity DID,you may need to add service information which indicates the * type of service,You can modify this value but note that. there is a length limit - * */ - public static String serviceType = "drivingCardService"; + public static final String SERVICE_TYPE = "drivingCardService"; /** - * after you create weIdentity DID,you may need to add service information which indicates the + * after you create WeIdentity DID,you may need to add service information which indicates the * serviceEndpoint of service,You can modify this value. - * */ - public static String serviceEndpoint = "https://weidentity.webank.com/endpoint/xxxxx"; + public static final String SERVICE_ENDPOINT = "https://weidentity.webank.com/endpoint/xxxxx"; /** * you may need to add authorization after you create weId,This property is the public key * type,but for now the value is fixed and you don't need to modify it. - * */ - public static String authenticationType = "RsaSignatureAuthentication2018"; + public static final String AUTHENTICATION_TYPE = "RsaSignatureAuthentication2018"; /** * when you register an authority,you may need to get a name,which indicates the name of the * authority. - * */ - public static String authorityIssuerName = "weBank"; + public static final String AUTHORITY_ISSUER_NAME = "weBank"; /** * when you register an authority,you may need to get a accValue,which indicates the accValue of * the authority, the default value for testing is 0. - * */ - public static String authorityIssuerAccValue = "0"; - - /** a valid jsonSchema template needed to register CPT. */ - public static String schema = - "{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"/etc/fstab\",\"description\":\"JSON representation of /etc/fstab\",\"type\":\"object\",\"properties\":{\"swap\":{\"$ref\":\"#/definitions/mntent\"}},\"patternProperties\":{\"^/([^/]+(/[^/]+)*)?$\":{\"$ref\":\"#/definitions/mntent\"}},\"required\":[\"/\",\"swap\"],\"additionalProperties\":false,\"definitions\":{\"mntent\":{\"title\":\"mntent\",\"description\":\"An fstab entry\",\"type\":\"object\",\"properties\":{\"device\":{\"type\":\"string\"},\"fstype\":{\"type\":\"string\"},\"options\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"string\"}},\"dump\":{\"type\":\"integer\",\"minimum\":0},\"fsck\":{\"type\":\"integer\",\"minimum\":0}},\"required\":[\"device\",\"fstype\"],\"additionalItems\":false}}}"; + public static final String AUTHORITY_ISSUER_ACCVALUE = "0"; - /** valid data corresponding to template in CPT. */ - public static String schemaData = - "{\"/\":{\"device\":\"/dev/sda2\",\"fstype\":\"btrfs\",\"options\":[\"ssd\"]},\"swap\":{\"device\":\"/dev/sda2\",\"fstype\":\"swap\"},\"/tmp\":{\"device\":\"tmpfs\",\"fstype\":\"tmpfs\",\"options\":[\"size=64M\"]},\"/var/lib/mysql\":{\"device\":\"/dev/data/mysql\",\"fstype\":\"btrfs\"}}"; - - /** an invalid template may be required in the CPT registration case. */ - public static String schemaDataInvalid = - "{\"/\":{\"device111\":\"/dev/sda2\",\"fstype\":\"btrfs\",\"options\":[\"ssd\"]},\"swap\":{\"device\":\"/dev/sda2\",\"fstype\":\"swap\"},\"/tmp\":{\"device\":\"tmpfs\",\"fstype\":\"tmpfs\",\"options\":[\"size=64M\"]},\"/var/lib/mysql\":{\"device\":\"/dev/data/mysql\",\"fstype\":\"btrfs\"}}"; + /** + * a valid jsonSchema template needed to register CPT. + */ + public static final String SCHEMA = + "{" + + " \"properties\" : {" + + " \"id\": {" + + " \"type\": \"string\", " + + " \"description\": \"the weid of certificate owner\"" + + " }, " + + " \"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\": [\"id\",\"name\", \"age\"]" + + "}"; } diff --git a/src/test/java/com/webank/weid/full/auth/TestAddIssuerIntoIssuerType.java b/src/test/java/com/webank/weid/full/auth/TestAddIssuerIntoIssuerType.java new file mode 100644 index 00000000..47702638 --- /dev/null +++ b/src/test/java/com/webank/weid/full/auth/TestAddIssuerIntoIssuerType.java @@ -0,0 +1,326 @@ +package com.webank.weid.full.auth; + +import com.webank.weid.util.WeIdUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public class TestAddIssuerIntoIssuerType extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestAddIssuerIntoIssuerType.class); + + private static CreateWeIdDataResult createWeId; + + private String issuerType = null; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.registerAuthorityIssuer(); + } + if (issuerType == null) { + issuerType = super.registerIssuerType("college"); + } + } + + /** + * case : test repeat add issuer into issuer type success. + */ + @Test + public void testAddIssuerIntoIssuerType_repeatFail() { + WeIdAuthentication weIdAuthentication = + TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + CreateWeIdDataResult weId = super.createWeId(); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, weId.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + + ResponseData res = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, weId.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", res); + + Assert.assertEquals(ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode(), + res.getErrorCode().intValue()); + Assert.assertFalse(res.getResult()); + } + + /** + * caller is not authority issuer . + */ + @Test + public void testAddIssuerIntoIssuerType_noAuthorityIssuer() { + WeIdAuthentication weIdAuthentication = + TestBaseUtil.buildWeIdAuthentication(super.createWeId()); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:caller has been remove register authority issuer,then call the api. + */ + @Test + public void testAddIssuerIntoIssuerType_removeAuthorityIssuer() { + CreateWeIdDataResult weId = super.registerAuthorityIssuer(); + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs + = TestBaseUtil.buildRemoveAuthorityIssuerArgs(weId, privateKey); + ResponseData res + = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + WeIdAuthentication weIdAuthentication = + TestBaseUtil.buildWeIdAuthentication(weId); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case : weId Authentication is null. + */ + @Test + public void testAddIssuerIntoIssuerType_callerNull() { + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: caller is blank. + */ + @Test + public void testAddIssuerIntoIssuerType_callerBlank() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId(""); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: caller is blank. + */ + @Test + public void testAddIssuerIntoIssuerType_invalidCaller() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId("!@#¥%……&*():,。"); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: private key is null. + */ + @Test + public void testAddIssuerIntoIssuerType_privateKeyNull() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeIdPrivateKey(null); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: private key is blank. + */ + @Test + public void testAddIssuerIntoIssuerType_privateKeyBlank() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(""); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: private key is belong other weId. + */ + @Test + public void testAddIssuerIntoIssuerType_otherPriKey() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeIdPrivateKey(createWeIdResult.getUserWeIdPrivateKey()); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: private key is belong other weId. + */ + @Test + public void testAddIssuerIntoIssuerType_otherAuthorPriKey() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + CreateWeIdDataResult weIdDataResult = super.registerAuthorityIssuer(); + authorityIssuerService + .recognizeAuthorityIssuer(weIdDataResult.getWeId(), new WeIdPrivateKey(privateKey)); + weIdAuthentication.setWeIdPrivateKey(weIdDataResult.getUserWeIdPrivateKey()); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, createWeIdResult.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case: public key is null. + */ + @Test + public void testAddIssuerIntoIssuerType_PubKeyNull() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + weIdAuthentication.setAuthenticationMethodId(null); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, super.createWeId().getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case: public key contain any special char. + */ + @Test + public void testAddIssuerIntoIssuerType_PubKeyContainChar() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (i % 127); + } + weIdAuthentication.setAuthenticationMethodId(String.valueOf(chars)); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, super.createWeId().getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case: issuer is not exist on chain. + */ + @Test + public void testAddIssuerIntoIssuerType_issuerNotExist() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, + "did:weid:0xc7e399b8d2da337f4e92eb33ca88b60b899ff022"); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + + /** + * case: invalid issuer. + */ + @Test + public void testAddIssuerIntoIssuerType_invalidIssuer() { + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, + "did:weid:0xc7e399b8d2da337f4e92eb33ca88b60b899"); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: Get RetIssuerType Count. + */ + @Test + public void testGetRetIssuerCountByIssuerType() { + ResponseData responseBefore = + authorityIssuerService.getSpecificTypeIssuerSize(issuerType); + LogUtil.info(logger, "getSpecificTypeIssuerSize", responseBefore); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseBefore.getErrorCode().intValue()); + + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + ResponseData response1 = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, issuerType, super.createWeId().getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertTrue(response1.getResult()); + + ResponseData responseAfter = + authorityIssuerService.getSpecificTypeIssuerSize(issuerType); + LogUtil.info(logger, "getSpecificTypeIssuerSize", responseAfter); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseAfter.getErrorCode().intValue()); + Assert.assertTrue((responseAfter.getResult() - responseBefore.getResult()) == 1); + } +} diff --git a/src/test/java/com/webank/weid/full/auth/TestGetAllAuthorityIssuerList.java b/src/test/java/com/webank/weid/full/auth/TestGetAllAuthorityIssuerList.java new file mode 100644 index 00000000..d2e89ef2 --- /dev/null +++ b/src/test/java/com/webank/weid/full/auth/TestGetAllAuthorityIssuerList.java @@ -0,0 +1,201 @@ +package com.webank.weid.full.auth; + +import java.math.BigInteger; +import java.util.List; + +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.fisco.bcos.sdk.crypto.keystore.KeyTool; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DataToolUtils; + + +public class TestGetAllAuthorityIssuerList extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestGetAllAuthorityIssuerList.class); + + private static CreateWeIdDataResult createWeId; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.registerAuthorityIssuer(); + } + } + + /** + * case:get all authority issuer list. + */ + + @Test + public void testGetAllAuthorityIssuerList_success() { + + ResponseData> response1 = + authorityIssuerService.getAllAuthorityIssuerList(0, 2); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); + } + + /** + * case:get all authority issuer list that index is minus. + */ + + @Test + public void testGetAllAuthorityIssuerList_indexIsMinus() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(-1, 2); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + } + + /** + * case:get all authority issuer list that num is minus. + */ + @Test + public void testGetAllAuthorityIssuerList_numIsMinus() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, -1); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + } + + /** + * case:get all authority issuer list that num is zero. + */ + @Test + public void testGetAllAuthorityIssuerList_numIsZero() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, 0); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:get all authority issuer list that num is zero. + */ + @Test + public void testGetAllAuthorityIssuerList_indexBigNum() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(999, 9); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(CollectionUtils.isEmpty(response.getResult())); + } + + + /** + * case:get all authority issuer list that index=0 and num=99. + */ + @Test + public void testGetAllAuthorityIssuerList_bigNum() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, 99); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:get all authority issuer list that index=0 and num=99. + */ + @Test + public void testGetAllAuthorityIssuerList_biggestNum() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, 50); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:get all authority issuer list that index=0 and num=99. + */ + @Test + public void testGetAllAuthorityIssuerList_removeListThenQuery() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, 5); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + List authorityIssuers = response.getResult(); + String sdkWeId = WeIdUtils.getWeIdFromPrivateKey(privateKey); + + for (int i = 0; i < authorityIssuers.size(); i++) { + String weId = authorityIssuers.get(i).getWeId(); + if (!weId.equals(createWeId.getWeId()) && !sdkWeId.equals(weId)) { + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + new RemoveAuthorityIssuerArgs(); + removeAuthorityIssuerArgs.setWeId(weId); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + removeAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + ResponseData info + = authorityIssuerService.queryAuthorityIssuerInfo(weId); + LogUtil.info(logger, "queryAuthorityIssuer", info); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + info.getErrorCode().intValue()); + } + } + } + + /** + * case:get all authority issuer list many times. + */ + @Test + public void testGetAllAuthorityIssuerList_queryMoreTimes() { + + ResponseData> response = + authorityIssuerService.getAllAuthorityIssuerList(0, 50); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData> response1 = + authorityIssuerService.getAllAuthorityIssuerList(1, 50); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + + ResponseData> response2 = + authorityIssuerService.getAllAuthorityIssuerList(1, 50); + LogUtil.info(logger, "TestGetAllAuthorityIssuerList", response2); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response2.getErrorCode().intValue()); + + } + +} diff --git a/src/test/java/com/webank/weid/full/auth/TestIsAuthorityIssuer.java b/src/test/java/com/webank/weid/full/auth/TestIsAuthorityIssuer.java index 08c0595c..55c1d74a 100644 --- a/src/test/java/com/webank/weid/full/auth/TestIsAuthorityIssuer.java +++ b/src/test/java/com/webank/weid/full/auth/TestIsAuthorityIssuer.java @@ -1,272 +1,230 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.auth; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.full.TestBaseServcie; +import com.webank.weid.util.DataToolUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +import java.math.BigInteger; /** * isAuthorityIssuer method for testing AuthorityIssuerService. - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestIsAuthorityIssuer extends TestBaseServcie { +public class TestIsAuthorityIssuer extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestIsAuthorityIssuer.class); private static CreateWeIdDataResult createWeId; @Override - public void testInit() throws Exception { + public synchronized void testInit() { + super.testInit(); if (createWeId == null) { createWeId = super.registerAuthorityIssuer(); - super.testInit(); } } /** - * case: is authority issuer. - * - * @throws Exception may be throw Exception + * case: is authority issuer success . */ - @Test - public void testIsAuthorityIssuerCase1() throws Exception { + //@Test + public void testIsAuthorityIssuerSuccess() { ResponseData response = authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); + LogUtil.info(logger, "isAuthorityIssuer", response); + Assert.assertFalse(response.getResult()); + AuthorityIssuer authorityIssuer = + authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()).getResult(); + Assert.assertFalse(authorityIssuer.isRecognized()); + response = authorityIssuerService.recognizeAuthorityIssuer(createWeId.getWeId(), + new WeIdPrivateKey(privateKey)); + Assert.assertTrue(response.getResult()); + response = authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); + Assert.assertTrue(response.getResult()); + authorityIssuer = + authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()).getResult(); + Assert.assertFalse(authorityIssuer.isRecognized()); + authorityIssuerService + .deRecognizeAuthorityIssuer(createWeId.getWeId(), new WeIdPrivateKey(privateKey)); + response = authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); + Assert.assertFalse(response.getResult()); + + response = authorityIssuerService.recognizeAuthorityIssuer( + createWeIdWithSetAttr().getWeId(), new WeIdPrivateKey(privateKey)); + Assert.assertFalse(response.getResult()); + Assert.assertEquals(response.getErrorCode().intValue(), + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode()); + + authorityIssuerService.recognizeAuthorityIssuer(createWeId.getWeId(), + new WeIdPrivateKey(privateKey)); + response = authorityIssuerService.deRecognizeAuthorityIssuer(createWeId.getWeId(), + new WeIdPrivateKey("11111111")); + Assert.assertFalse(response.getResult()); + Assert.assertEquals(response.getErrorCode().intValue(), + ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode()); } /** - * case: weIdentity DId is bad format. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testIsAuthorityIssuerCase2() throws Exception { + public void testIsAuthorityIssuerWeIdFormat() { - ResponseData response = authorityIssuerService.isAuthorityIssuer("xxxxxxxxxxx"); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = authorityIssuerService.isAuthorityIssuer("as~12345678>?<"); + LogUtil.info(logger, "isAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DId is blank. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is not exists. */ @Test - public void testIsAuthorityIssuerCase3() throws Exception { + public void testIsAuthorityIssuerWeIdSorted() { - ResponseData response = authorityIssuerService.isAuthorityIssuer(null); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + String weId = "weid:did:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d87733"; + ResponseData response = authorityIssuerService + .isAuthorityIssuer(weId); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId is registed by other. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is not start with 0x. */ @Test - public void testIsAuthorityIssuerCase4() throws Exception { + public void testIsAuthorityIssuerWeIdnotHex() { + String weId = "weid:did:00f3d8234e93823fac7ebdf0cfaa03b6a43d87733"; ResponseData response = authorityIssuerService - .isAuthorityIssuer("did:weid:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d8773b"); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + .isAuthorityIssuer(weId); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId is not exists. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is not start with space and end with space. */ @Test - public void testIsAuthorityIssuerCase5() throws Exception { + public void testIsAuthorityIssuerWeIdContainSpace() { + String weId = "weid:did:0xf3d8234e93823fac7ebdf0cfaa03b6a43d87733"; ResponseData response = authorityIssuerService - .isAuthorityIssuer("did:weid:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d87733"); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + .isAuthorityIssuer(weId); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId is removed. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is null. */ @Test - public void testIsAuthorityIssuerCase6() throws Exception { - - CreateWeIdDataResult createWeId = super.registerAuthorityIssuer(); + public void testIsAuthorityIssuerWeIdNull() { - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + ResponseData response = authorityIssuerService.isAuthorityIssuer(null); + LogUtil.info(logger, "isAuthorityIssuer", response); - ResponseData response = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); + /** + * case: WeIdentity DID is blank. + */ + @Test + public void testIsAuthorityIssuerWeIdBlank() { - response = authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = authorityIssuerService.isAuthorityIssuer(""); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: Simulation throws an InterruptedException when calling the - * isAuthorityIssuer method. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is registed by other. */ @Test - public void testIsAuthorityIssuerCase7() throws Exception { - - final MockUp> mockFuture = new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future isAuthorityIssuer(Address addr) throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testIsAuthorityIssuerWeIdNotRegister() { - ResponseData response = - authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); + String weId = createWeId().getWeId(); + ResponseData response = authorityIssuerService + .isAuthorityIssuer(weId); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: Simulation throws an TimeoutException when calling the - * isAuthorityIssuer method. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is not exists. */ @Test - public void testIsAuthorityIssuerCase8() throws Exception { - - final MockUp> mockFuture = new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future isAuthorityIssuer(Address addr) throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testIsAuthorityIssuerWeIdNotExist() { - ResponseData response = - authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); + ResponseData response = authorityIssuerService + .isAuthorityIssuer("did:weid:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d87733"); + LogUtil.info(logger, "isAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: Simulation returns null when invoking the isAuthorityIssuer method. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is removed. */ @Test - public void testIsAuthorityIssuerCase9() throws Exception { + public void testIsAuthorityIssuerRemovedWeId() { + + CreateWeIdDataResult createWeId = super.registerAuthorityIssuer(); + LogUtil.info(logger, "registerAuthorityIssuer", createWeId); - MockUp mockTest = new MockUp() { - @Mock - public Future isAuthorityIssuer(Address addr) throws Exception { - return null; - } - }; + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId, privateKey); ResponseData response = - authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); - System.out.println("\nisAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "isAuthorityIssuer", response); - mockTest.tearDown(); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), + response = authorityIssuerService.isAuthorityIssuer(createWeId.getWeId()); + LogUtil.info(logger, "isAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + } diff --git a/src/test/java/com/webank/weid/full/auth/TestQueryAuthorityIssuerInfo.java b/src/test/java/com/webank/weid/full/auth/TestQueryAuthorityIssuerInfo.java index ed88ec96..094f77e4 100644 --- a/src/test/java/com/webank/weid/full/auth/TestQueryAuthorityIssuerInfo.java +++ b/src/test/java/com/webank/weid/full/auth/TestQueryAuthorityIssuerInfo.java @@ -1,314 +1,206 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.auth; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.full.TestBaseServcie; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Type; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DateUtils; /** * queryAuthorityIssuerInfo method for testing AuthorityIssuerService. - * - * @author v_wbgyang * + * @author v_wbgyang/rockyxia */ -public class TestQueryAuthorityIssuerInfo extends TestBaseServcie { +public class TestQueryAuthorityIssuerInfo extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestQueryAuthorityIssuerInfo.class); private static CreateWeIdDataResult createWeId; @Override - public void testInit() throws Exception { + public synchronized void testInit() { + super.testInit(); if (createWeId == null) { createWeId = super.registerAuthorityIssuer(); - super.testInit(); } } /** * case: query success. - * - * @throws Exception may be throw Exception */ @Test - public void testQueryAuthorityIssuerInfoCase1() throws Exception { + public void testQueryAuthorityIssuerInfo_success() { ResponseData response = authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } /** - * case: weIdentity DId is blank. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is null. */ @Test - public void testQueryAuthorityIssuerInfoCase2() throws Exception { + public void testQueryAuthorityIssuerInfo_weIdNull() { ResponseData response = authorityIssuerService.queryAuthorityIssuerInfo(null); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } /** - * case: weIdentity DId is bad format. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is blank. */ @Test - public void testQueryAuthorityIssuerInfoCase3() throws Exception { + public void testQueryAuthorityIssuerInfo_weIdBlank() { ResponseData response = - authorityIssuerService.queryAuthorityIssuerInfo("xx:xx:xxxxxxx"); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + authorityIssuerService.queryAuthorityIssuerInfo(""); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } /** - * case: weIdentity DId is not exists. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testQueryAuthorityIssuerInfoCase4() throws Exception { + public void testQueryAuthorityIssuerInfo_weIdFormat() { - ResponseData response = authorityIssuerService - .queryAuthorityIssuerInfo("did:weid:0xc7e399b8d2da337f4e92eb33ca88b60b899b5022"); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + ResponseData response = + authorityIssuerService.queryAuthorityIssuerInfo("xx:xx:xxxxxxx"); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } /** - * case: weIdentity DId is registed by other. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is invalid. */ @Test - public void testQueryAuthorityIssuerInfoCase5() throws Exception { + public void testQueryAuthorityIssuerInfo_invalidWeId() { ResponseData response = authorityIssuerService - .queryAuthorityIssuerInfo("did:weid:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d8773b"); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + .queryAuthorityIssuerInfo("123!@#$%^&*()/.,,-=+gt中国yyyyyy$%^&*fsdfdfdfdd"); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } /** - * case: weIdentity DId is removed. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not exists. */ @Test - public void testQueryAuthorityIssuerInfoCase6() throws Exception { - - CreateWeIdDataResult createWeId = super.registerAuthorityIssuer(); - - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - - ResponseData response = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response); + public void testQueryAuthorityIssuerInfo_weIdNotExist() { - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - - ResponseData response1 = - authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response1); + ResponseData response = authorityIssuerService + .queryAuthorityIssuerInfo("did:weid:0xc7e399b8d2da337f4e92eb33ca88b60b899b5022"); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response1.getErrorCode().intValue()); - Assert.assertNull(response1.getResult()); + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); } /** - * case: mock an InterruptedException. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not registed. */ @Test - public void testQueryAuthorityIssuerInfoCase7() throws Exception { - - final MockUp>>> mockFuture = new MockUp>>>() { - @Mock - public Future>> get(long timeout, TimeUnit unit) throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future>> getAuthorityIssuerInfoNonAccValue(Address addr) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = - authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + public void testQueryAuthorityIssuerInfo_weIdNotRegister() { - mockTest.tearDown(); - mockFuture.tearDown(); + String weId = createWeId().getWeId(); + ResponseData response = authorityIssuerService + .queryAuthorityIssuerInfo(weId); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } /** - * case: mock an TimeoutException. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is removed then query. */ @Test - public void testQueryAuthorityIssuerInfoCase8() throws Exception { - - final MockUp>>> mockFuture = new MockUp>>>() { - @Mock - public Future>> get(long timeout, TimeUnit unit) throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future>> getAuthorityIssuerInfoNonAccValue(Address addr) - throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testQueryAuthorityIssuerInfo_weIdRemoved() { - ResponseData response = - authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + CreateWeIdDataResult createWeId = super.registerAuthorityIssuer(); + LogUtil.info(logger, "registerAuthorityIssuer", createWeId); - mockTest.tearDown(); - mockFuture.tearDown(); + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId, privateKey); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } + ResponseData response = + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "removeAuthorityIssuer", response); - /** - * case: mock returns null when invoking the future.get(). - * - * @throws Exception may be throw Exception - */ - @Test - public void testQueryAuthorityIssuerInfoCase9() throws Exception { - - final MockUp>>> mockFuture = new MockUp>>>() { - @Mock - public Future>> get(long timeout, TimeUnit unit) throws Exception { - return null; - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future>> getAuthorityIssuerInfoNonAccValue(Address addr) - throws Exception { - return mockFuture.getMockInstance(); - } - }; + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - ResponseData response = + ResponseData response1 = authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + response1.getErrorCode().intValue()); + Assert.assertNull(response1.getResult()); } /** - * case: mock an NullPointerException. - * - * @throws Exception may be throw Exception + * case: register issuer that create time is after now, then query the issuer. */ @Test - public void testQueryAuthorityIssuerInfoCase10() throws Exception { + public void testQueryAuthorityIssuerInfo_createFuture() { + + String weId = createWeId().getWeId(); + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId(weId); + authorityIssuer.setName("zhbank" + Math.random()); + authorityIssuer.setAccValue("0"); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); + registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuer); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + registerAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setCreated(DateUtils.getNoMillisecondTimeStamp() + 1000000); - MockUp mockTest = new MockUp() { - @Mock - public Future>> getAuthorityIssuerInfoNonAccValue(Address addr) - throws Exception { - return null; - } - }; + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); - ResponseData response = - authorityIssuerService.queryAuthorityIssuerInfo(createWeId.getWeId()); - System.out.println("\nqueryAuthorityIssuerInfo result:"); - BeanUtil.print(response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - mockTest.tearDown(); + ResponseData response1 = + authorityIssuerService.queryAuthorityIssuerInfo(weId); + LogUtil.info(logger, "queryAuthorityIssuerInfo", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); } } diff --git a/src/test/java/com/webank/weid/full/auth/TestRegisterAuthorityIssuer.java b/src/test/java/com/webank/weid/full/auth/TestRegisterAuthorityIssuer.java index dae16d4b..ed5e392c 100644 --- a/src/test/java/com/webank/weid/full/auth/TestRegisterAuthorityIssuer.java +++ b/src/test/java/com/webank/weid/full/auth/TestRegisterAuthorityIssuer.java @@ -1,182 +1,231 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify it under the terms of - * the GNU Lesser General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.auth; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.contract.AuthorityIssuerController.AuthorityIssuerRetLogEventResponse; -import com.webank.weid.full.TestBaseServcie; +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.AuthorityIssuer; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DateUtils; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; /** * registerAuthorityIssuer method for testing AuthorityIssuerService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestRegisterAuthorityIssuer extends TestBaseServcie { +public class TestRegisterAuthorityIssuer extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestRegisterAuthorityIssuer.class); /** - * case: weIdentity DId is invalid. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is invalid. */ @Test - public void testRegisterAuthorityIssuerCase1() throws Exception { + public void testRegisterAuthorityIssuer_invalidWeId() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer().setWeId("xxxxxxxxxxxxxxxx"); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("registerAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DId is bad format. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testRegisterAuthorityIssuerCase2() throws Exception { + public void testRegisterAuthorityIssuer_weIdFormat() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer() - .setWeId("di:weid:0x29f3fe8d4536966af41392f7ddc756b6f452df02"); + .setWeId("di:weid:0x29f3fe8d4536966af41392f7ddc756b6f452df02"); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("registerAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId address is not exists. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID address is not exists. */ @Test - public void testRegisterAuthorityIssuerCase3() throws Exception { + public void testRegisterAuthorityIssuer_weIdNotExist() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer() - .setWeId("did:weid:0x29f3" + System.currentTimeMillis()); + .setWeId("did:weid:0x29f3" + System.currentTimeMillis()); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("registerAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId is null or "" or " ". - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is null or "" or " ". */ @Test - public void testRegisterAuthorityIssuerCase4() throws Exception { + public void testRegisterAuthorityIssuer_weIdNull() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer().setWeId(null); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("registerAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the name is blank. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is null or "" or " ". */ @Test - public void testRegisterAuthorityIssuerCase5() throws Exception { + public void testRegisterAuthorityIssuer_weIdBlank() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - registerAuthorityIssuerArgs.getAuthorityIssuer().setName(null); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setWeId(""); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the created before now ,now or after now. - * - * @throws Exception may be throw Exception + * case: the created after now. */ @Test - public void testRegisterAuthorityIssuerCase6() throws Exception { + public void testRegisterAuthorityIssuer_createFuture() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setCreated(DateUtils.getNoMillisecondTimeStamp() + 4000); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: the created before now . + */ + @Test + public void testRegisterAuthorityIssuer_createPassed() { CreateWeIdDataResult createWeId = super.createWeId(); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer() - .setCreated(System.currentTimeMillis() + 4000); + .setCreated(DateUtils.getNoMillisecondTimeStamp() - 4000); - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: the created is null. + */ + @Test + public void testRegisterAuthorityIssuer_createNull() { + + CreateWeIdDataResult createWeId = super.createWeId(); + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setCreated(null); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: the created is 19600101. + */ + @Test + public void testRegisterAuthorityIssuer_create19600101() { + + CreateWeIdDataResult createWeId = super.createWeId(); + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setCreated(-19600101L); + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); @@ -184,92 +233,388 @@ public void testRegisterAuthorityIssuerCase6() throws Exception { /** * case: the accValue is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase7() throws Exception { + public void testRegisterAuthorityIssuer_accValueNull() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue(null); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: the accValue is null. + */ + @Test + public void testRegisterAuthorityIssuer_accValueBlank() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue(""); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: the accValue is any spec. + */ + @Test + public void testRegisterAuthorityIssuer_accValueSpecialChar() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue("adssdf"); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), - response.getErrorCode().intValue()); + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + /** + * case: the accValue is any spec. + */ + @Test + public void testRegisterAuthorityIssuer_accValueIsInteger() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue("123456789"); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: the accValue is any spec. + */ + @Test + public void testRegisterAuthorityIssuer_accValueIsFloat() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue("123456789.2"); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * Happy path: register full authority issuer info. + */ + @Test + public void testRegisterAuthorityIssuer_FullInfo() { + CreateWeIdDataResult createWeIdDataResult = createWeIdWithSetAttr(); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdDataResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName("temp" + Math.random()); + String desc = "WB1"; + registerAuthorityIssuerArgs.getAuthorityIssuer().setDescription(desc); + List extraStr = new ArrayList<>(); + extraStr.add("temp"); + extraStr.add("test"); + registerAuthorityIssuerArgs.getAuthorityIssuer().setExtraStr32(extraStr); + List extraInt = new ArrayList<>(); + extraInt.add(123); + extraInt.add(234); + registerAuthorityIssuerArgs.getAuthorityIssuer().setExtraInt(extraInt); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + Assert.assertEquals(true, response.getResult()); + + ResponseData queryResp = + authorityIssuerService.queryAuthorityIssuerInfo(createWeIdDataResult.getWeId()); + Assert.assertEquals(queryResp.getResult().getDescription(), desc); + Assert.assertEquals(queryResp.getResult().getExtraStr32(), extraStr); + Assert.assertEquals(queryResp.getResult().getExtraInt(), extraInt); + } + + /** + * Register authority issuer info with erroneous params. + */ + @Test + public void testRegisterAuthorityIssuer_ErroneousInfo() { + CreateWeIdDataResult createWeIdDataResult = createWeIdWithSetAttr(); + RegisterAuthorityIssuerArgs arg = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdDataResult, privateKey); + arg.getAuthorityIssuer().setName("temp" + Math.random()); + String desc = "WB1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + arg.getAuthorityIssuer().setDescription(desc); + Assert.assertFalse(authorityIssuerService.registerAuthorityIssuer(arg).getResult()); + + desc = "WB1"; + arg.getAuthorityIssuer().setDescription(desc); + List extraStr = new ArrayList<>(); + extraStr.add("temp"); + extraStr.add("WB1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + arg.getAuthorityIssuer().setExtraStr32(extraStr); + Assert.assertFalse(authorityIssuerService.registerAuthorityIssuer(arg).getResult()); + + extraStr = new ArrayList<>(); + for (int i = 0; i < 12; i++) { + extraStr.add("temp"); + } + arg.getAuthorityIssuer().setExtraStr32(extraStr); + Assert.assertFalse(authorityIssuerService.registerAuthorityIssuer(arg).getResult()); + + arg.getAuthorityIssuer().setExtraStr32(new ArrayList<>()); + List extraInt = new ArrayList<>(); + for (int i = 0; i < 12; i++) { + extraInt.add(123); + } + arg.getAuthorityIssuer().setExtraInt(extraInt); + Assert.assertFalse(authorityIssuerService.registerAuthorityIssuer(arg).getResult()); + } + + /** + * case: the accValue is any spec. + */ + @Test + public void testRegisterAuthorityIssuer_accValueIsNegInteger() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setAccValue("-123456"); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: no acc value. + */ + @Test + public void testRegisterAuthorityIssuer_noAccValue() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId(registerAuthorityIssuerArgs.getAuthorityIssuer().getWeId()); + authorityIssuer.setName("hk123"); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs1 = + new RegisterAuthorityIssuerArgs(); + registerAuthorityIssuerArgs1 + .setAuthorityIssuer(authorityIssuer); + registerAuthorityIssuerArgs1 + .setWeIdPrivateKey(registerAuthorityIssuerArgs.getWeIdPrivateKey()); + ResponseData response1 = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs1); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ACCVALUE_ILLEAGAL.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); + } + /** * case: registerAuthorityIssuer success. - * - * @throws Exception may be throw Exception */ + @Test - public void testRegisterAuthorityIssuerCase8() throws Exception { + public void testRegisterAuthorityIssuer_weIdUpper() { CreateWeIdDataResult createWeId = super.createWeId(); + createWeId.setWeId(createWeId.getWeId().toUpperCase()); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + + /** + * case: registerAuthorityIssuer with Chinese Name (utf-8). + */ + @Test + public void testRegisterAuthorityIssuerChineseName() { + + final CreateWeIdDataResult weId = super.createWeId(); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(weId, privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + String chiName = null; + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + chiName = "中文" + DateUtils.getCurrentTimeStampString(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(chiName); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); + + ResponseData queryResponse = authorityIssuerService + .queryAuthorityIssuerInfo(weId.getWeId()); + Assert.assertTrue(queryResponse.getResult().getName().equalsIgnoreCase(chiName)); + ResponseData weIdresp = authorityIssuerService.getWeIdByOrgId(chiName); + Assert.assertTrue(weIdresp.getResult().equalsIgnoreCase(weId.getWeId())); } /** - * case: the weIdentity DId is registed. - * - * @throws Exception may be throw Exception + * case: registerAuthorityIssuer success. */ @Test - public void testRegisterAuthorityIssuerCase9() throws Exception { + public void testRegisterAuthorityIssuer_weIdTooLong() { CreateWeIdDataResult createWeId = super.createWeId(); + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (i % 127); + } + String weId = String.valueOf(chars); + createWeId.setWeId(weId); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: the WeIdentity DID is registed. + */ + @Test + public void testRegisterAuthorityIssuer_repeat() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); ResponseData response1 = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response1); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response1); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode(), - response1.getErrorCode().intValue()); + response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: registerAuthorityIssuerArgs is null. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID has been registed,issuer name is different. */ @Test - public void testRegisterAuthorityIssuerCase10() throws Exception { + public void testRegisterAuthorityIssuer_weIdHasRegister() { + + final CreateWeIdDataResult weId = super.createWeId(); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(weId, privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = null; + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName("weId 已经被注册" + (int)(Math.random() * 10000)); + ResponseData response1 = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response1); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); + } + + /** + * case: registerAuthorityIssuerArgs is null. + */ + @Test + public void testRegisterAuthorityIssuer_argsNull() { + RegisterAuthorityIssuerArgs args = new RegisterAuthorityIssuerArgs(); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(args); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); @@ -277,20 +622,17 @@ public void testRegisterAuthorityIssuerCase10() throws Exception { /** * case: authorityIssuer is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase11() throws Exception { + public void testRegisterAuthorityIssuer_authorityIssuerNull() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.setAuthorityIssuer(null); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); @@ -298,280 +640,424 @@ public void testRegisterAuthorityIssuerCase11() throws Exception { /** * case: weIdPrivateKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase12() throws Exception { + public void testRegisterAuthorityIssuer_priKeyNull() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.setWeIdPrivateKey(null); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), - response.getErrorCode().intValue()); + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** * case: privateKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase13() throws Exception { + public void testRegisterAuthorityIssuer_setPriKeyNull() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(null); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: privateKey is blank. + */ + @Test + public void testRegisterAuthorityIssuer_setPriKeyBlank() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(""); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), - response.getErrorCode().intValue()); + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** * case: privateKey is invalid. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase14() throws Exception { + public void testRegisterAuthorityIssuer_invalidPrikey() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey("xxxxxxx"); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), - response.getErrorCode().intValue()); + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey and private key of weIdentity DId do not match. - * - * @throws Exception may be throw Exception + * case: privateKey is valid but is a random integer. */ - @Test - public void testRegisterAuthorityIssuerCase15() throws Exception { + public void testRegisterAuthorityIssuer_prikeyIsInteger() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - registerAuthorityIssuerArgs.getWeIdPrivateKey() - .setPrivateKey(TestBaseUtil.createEcKeyPair()[1]); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey("123456789"); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey belongs to the private key of other weIdentity DId. - * - * @throws Exception may be throw Exception + * case: privateKey belongs to the private key of other WeIdentity DID. */ - @Test - public void testRegisterAuthorityIssuerCase16() throws Exception { + public void testRegisterAuthorityIssuer_otherPrivateKey() { CreateWeIdDataResult createWeId = super.createWeId(); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); registerAuthorityIssuerArgs.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** * case: the private key is the private key of the members of the committee. - * - * @throws Exception may be throw Exception */ @Test - public void testRegisterAuthorityIssuerCase17() throws Exception { + public void testRegisterAuthorityIssuerCase17() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(issuerPrivateList.get(1)); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName( + String.valueOf(System.currentTimeMillis())); + registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(issuerPrivateList.get(0)); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + Assert.assertEquals(true, response.getResult()); } /** - * case: mock an InterruptedException. - * - * @throws Exception may be throw Exception + * case: authorityIssuer.name is already exist. */ @Test - public void testRegisterAuthorityIssuerCase18() throws Exception { + public void testRegisterAuthorityIssuer_issuerNameOnly() { + + CreateWeIdDataResult createWeId = super.createWeId(); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + String name = null; + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); - final MockUp> mockFuture = - new MockUp>() { + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs1 + = TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + registerAuthorityIssuerArgs1.getAuthorityIssuer().setName( + registerAuthorityIssuerArgs.getAuthorityIssuer().getName()); + ResponseData response1 + = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs1); + + Assert.assertNotEquals(registerAuthorityIssuerArgs.getAuthorityIssuer().getWeId(), + registerAuthorityIssuerArgs1.getAuthorityIssuer().getWeId()); + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); - MockUp mockTest = new MockUp() { - @Mock - public Future addAuthorityIssuer(Address addr, - StaticArray attribBytes32, StaticArray attribInt, - DynamicBytes accValue) throws Exception { + } - return mockFuture.getMockInstance(); - } - }; + /** + * one WeId can not register one more AuthorityIssuer with diferent name. + */ + @Test + public void testRegisterAuthorityIssuer_registerIssuers() { - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + CreateWeIdDataResult createWeId = super.createWeId(); - mockTest.tearDown(); - mockFuture.tearDown(); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + String name = null; + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId(registerAuthorityIssuerArgs.getAuthorityIssuer().getWeId()); + authorityIssuer.setName(name + 1); + authorityIssuer.setAccValue("0"); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs1 + = new RegisterAuthorityIssuerArgs(); + registerAuthorityIssuerArgs1.setAuthorityIssuer(authorityIssuer); + registerAuthorityIssuerArgs1 + .setWeIdPrivateKey(registerAuthorityIssuerArgs.getWeIdPrivateKey()); + ResponseData response1 = authorityIssuerService + .registerAuthorityIssuer(registerAuthorityIssuerArgs1); + + Assert.assertEquals(registerAuthorityIssuerArgs.getAuthorityIssuer().getWeId(), + registerAuthorityIssuerArgs1.getAuthorityIssuer().getWeId()); + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_ALREADY_EXIST.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); } /** - * case: mock an TimeoutException. - * - * @throws Exception may be throw Exception + * one WeId can not register one more AuthorityIssuer with diferent name. */ @Test - public void testRegisterAuthorityIssuerCase19() throws Exception { + public void testRegisterAuthorityIssuer_noIssuerName() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + + AuthorityIssuer authorityIssuer = new AuthorityIssuer(); + authorityIssuer.setWeId(registerAuthorityIssuerArgs.getAuthorityIssuer().getWeId()); + authorityIssuer.setAccValue("0"); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs1 + = new RegisterAuthorityIssuerArgs(); + registerAuthorityIssuerArgs1.setAuthorityIssuer(authorityIssuer); + registerAuthorityIssuerArgs1 + .setWeIdPrivateKey(registerAuthorityIssuerArgs.getWeIdPrivateKey()); + ResponseData response1 = authorityIssuerService + .registerAuthorityIssuer(registerAuthorityIssuerArgs1); - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); - MockUp mockTest = new MockUp() { - @Mock - public Future addAuthorityIssuer(Address addr, - StaticArray attribBytes32, StaticArray attribInt, - DynamicBytes accValue) throws Exception { + } - return mockFuture.getMockInstance(); - } - }; + /** + * case: authorityIssuer.name is digtal. + */ + @Test + public void testRegisterAuthorityIssuer_issuerNameIsDigtal() { - ResponseData response = + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName("12435367890" + Math.random() * 10); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + } - mockTest.tearDown(); - mockFuture.tearDown(); + LogUtil.info(logger, "registerAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: authorityIssuer.name is too long. + */ + @Test + public void testRegisterAuthorityIssuer_issuerTooLong() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: mock returns null when invoking the getAuthorityIssuerRetLogEvents. - * - * @throws Exception may be throw Exception + * case: authorityIssuer.name contain zh. */ @Test - public void testRegisterAuthorityIssuerCase20() throws Exception { + public void testRegisterAuthorityIssuer_issuerNameContainZh() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); - MockUp mockTest = new MockUp() { - @Mock - public List getAuthorityIssuerRetLogEvents( - TransactionReceipt transactionReceipt) { - List list = - new ArrayList(); - list.add(null); - return list; - } - }; + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName("公安行政系统" + (int)(Math.random() * 10000)); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); - mockTest.tearDown(); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), - response.getErrorCode().intValue()); + /** + * case: authorityIssuer.name is null. + */ + @Test + public void testRegisterAuthorityIssuer_issuerNameNull() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName(null); + + ResponseData response = + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: authorityIssuer.name is too long. - * - * @throws Exception may be throw Exception + * case: authorityIssuer.name is blank. */ @Test - public void testRegisterAuthorityIssuerCase21() throws Exception { + public void testRegisterAuthorityIssuer_issuerNameBlank() { RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeIdResult, privateKey); registerAuthorityIssuerArgs.getAuthorityIssuer() - .setName("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + .setName(""); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_NAME_ILLEGAL.getCode(), - response.getErrorCode().intValue()); + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + + /** + * case: authorityIssuer.name contains Special character. + */ + @Test + public void testRegisterAuthorityIssuer_issuerNameContainsSpecialChar() { + + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(super.createWeId(), privateKey); + + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + registerAuthorityIssuerArgs.getAuthorityIssuer() + .setName("!@#¥%……&*-+<>?x" + (int)(Math.random() * 1000)); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: getIssuerCount. + */ + @Test + public void testGetIssuerCount() { + ResponseData responseBefore = + authorityIssuerService.getIssuerCount(); + LogUtil.info(logger, "getIssuerCount", responseBefore); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseBefore.getErrorCode().intValue()); + + super.registerAuthorityIssuer(); + + ResponseData responseAfter = authorityIssuerService.getIssuerCount(); + LogUtil.info(logger, "getIssuerCount", responseAfter); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseAfter.getErrorCode().intValue()); + Assert.assertTrue((responseAfter.getResult() - responseBefore.getResult()) == 1); + } + + /** + * case: getRecognizedIssuerCount. + */ + @Test + public void testGetRecognizedIssuerCount() { + ResponseData responseBefore = + authorityIssuerService.getRecognizedIssuerCount(); + LogUtil.info(logger, "getRecognizedIssuerCount", responseBefore); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseBefore.getErrorCode().intValue()); + + CreateWeIdDataResult registerAuthorityIssuer = super.registerAuthorityIssuer(); + ResponseData recognizeAuthorityIssuer = + authorityIssuerService.recognizeAuthorityIssuer( + registerAuthorityIssuer.getWeId(), + new WeIdPrivateKey(privateKey) + ); + LogUtil.info(logger, "recognizeAuthorityIssuer", recognizeAuthorityIssuer); + Assert.assertTrue(recognizeAuthorityIssuer.getResult()); + + ResponseData responseAfter = authorityIssuerService.getRecognizedIssuerCount(); + LogUtil.info(logger, "getRecognizedIssuerCount", responseAfter); + Assert.assertTrue((responseAfter.getResult() - responseBefore.getResult()) == 1); + } } diff --git a/src/test/java/com/webank/weid/full/auth/TestRegisterIssuerType.java b/src/test/java/com/webank/weid/full/auth/TestRegisterIssuerType.java new file mode 100644 index 00000000..99616251 --- /dev/null +++ b/src/test/java/com/webank/weid/full/auth/TestRegisterIssuerType.java @@ -0,0 +1,281 @@ + + +package com.webank.weid.full.auth; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.IssuerType; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * testing basic method classes. + * + * @author rocky + */ +public class TestRegisterIssuerType extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestIsAuthorityIssuer.class); + + private static CreateWeIdDataResult createWeId; + + private static final String issuerType = "police office"; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.createWeId(); + } + + } + + /** + * case:Register issuer type success. + */ + + public void testRegisterIssuerType_success() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + + ResponseData response = new ResponseData<>(false, + ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode()) { + response = authorityIssuerService.registerIssuerType(weIdAuthentication, issuerType); + } + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case:Register issuer type success. + */ + @Test + public void testRegisterIssuerType_successZh() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + + ResponseData response = new ResponseData<>(false, + ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode()) { + String name = "中国" + Math.random(); + response = authorityIssuerService.registerIssuerType(weIdAuthentication, name); + } + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case:when issuerType is accii,Register issuer type success. + */ + @Test + public void testRegisterIssuerType_successAscii() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + + ResponseData response = new ResponseData<>(false, + ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS); + char[] chars = new char[10]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (Math.random() % 127); + } + while (response.getErrorCode() + == ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode()) { + String name = String.valueOf(chars) + Math.random(); + response = authorityIssuerService.registerIssuerType(weIdAuthentication, name); + } + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult()); + } + + /** + * case:Register issuer type is blank. + */ + @Test + public void testRegisterIssuerType_issuerTypeNull() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, null); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:Register issuer type is blank. + */ + @Test + public void testRegisterIssuerType_issuerTypeBlank() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, ""); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + @Test + public void testRegisterIssuerType_issuerTypeTooLong() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + char[] chars = new char[33]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (Math.random() % 127); + } + String name = String.valueOf(chars); + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, name); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.SPECIFIC_ISSUER_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: weid not exist. + */ + @Test + public void testRegisterIssuerType_weidNotExist() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId("did:weid:0xc7e399b8d2da337f4e92eb33ca88b60b899ff022"); + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, "ttrr"); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: weid is null. + */ + @Test + public void testRegisterIssuerType_weidNull() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId(null); + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, "xx"); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: weid is blank. + */ + @Test + public void testRegisterIssuerType_weIdBlank() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId(""); + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, "xxx"); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: weid is invalid. + */ + @Test + public void testRegisterIssuerType_invalidWeId() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeId); + weIdAuthentication.setWeId("123sdf中国@#¥%……&*90()-+、《》·nm"); + ResponseData response = + authorityIssuerService.registerIssuerType(weIdAuthentication, "xxxxx"); + LogUtil.info(logger, "registerIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case: Get RetIssuerType Count. + */ + @Test + public void testGetRetIssuerTypeCount() { + ResponseData responseBefore = authorityIssuerService.getIssuerTypeCount(); + LogUtil.info(logger, "getIssuerTypeCount", responseBefore); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseBefore.getErrorCode().intValue()); + + String typeName = String.valueOf(System.currentTimeMillis()); + super.registerIssuerType(typeName); + + ResponseData responseAfter = authorityIssuerService.getIssuerTypeCount(); + LogUtil.info(logger, "getIssuerTypeCount", responseAfter); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseAfter.getErrorCode().intValue()); + Assert.assertTrue((responseAfter.getResult() - responseBefore.getResult()) == 1); + + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthentication(createWeIdNew); + ResponseData removeRes = authorityIssuerService.removeIssuerType( + weIdAuthentication, typeName); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), removeRes.getErrorCode().intValue()); + Assert.assertTrue(removeRes.getResult()); + + responseAfter = authorityIssuerService.getIssuerTypeCount(); + LogUtil.info(logger, "getIssuerTypeCount", responseAfter); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseAfter.getErrorCode().intValue()); + Assert.assertTrue(responseAfter.getResult() == responseBefore.getResult()); + } + + @Test + public void getIssuerTypeList() { + super.registerIssuerType(String.valueOf(System.currentTimeMillis())); + ResponseData> response = + authorityIssuerService.getIssuerTypeList(0, 1); + LogUtil.info(logger, "getIssuerTypeList", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().size() == 1); + Assert.assertNotNull(response.getResult().get(0).getOwner()); + Assert.assertNotNull(response.getResult().get(0).getTypeName()); + Assert.assertNotNull(response.getResult().get(0).getCreated()); + } +} diff --git a/src/test/java/com/webank/weid/full/auth/TestRemoveAuthorityIssuer.java b/src/test/java/com/webank/weid/full/auth/TestRemoveAuthorityIssuer.java index ba5b0c93..a3a67279 100644 --- a/src/test/java/com/webank/weid/full/auth/TestRemoveAuthorityIssuer.java +++ b/src/test/java/com/webank/weid/full/auth/TestRemoveAuthorityIssuer.java @@ -1,229 +1,232 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.auth; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.AuthorityIssuerController; -import com.webank.weid.contract.AuthorityIssuerController.AuthorityIssuerRetLogEventResponse; -import com.webank.weid.full.TestBaseServcie; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * removeAuthorityIssuer method for testing AuthorityIssuerService. - * - * @author v_wbgyang * + * @author v_wbgyang/rockyxia */ -public class TestRemoveAuthorityIssuer extends TestBaseServcie { +public class TestRemoveAuthorityIssuer extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestRemoveAuthorityIssuer.class); /** - * case: weIdentity DId is invalid. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is invalid. */ @Test - public void testRemoveAuthorityIssuerCase1() throws Exception { + public void testRemoveAuthorityIssuer_invalidWeId() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.setWeId("xxxxxxxx"); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.setWeId("x123~-=> response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DId is blank. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is null. */ @Test - public void testRemoveAuthorityIssuerCase2() throws Exception { + public void testRemoveAuthorityIssuer_weIdNull() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); removeAuthorityIssuerArgs.setWeId(null); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DId is bad format. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is blank. */ @Test - public void testRemoveAuthorityIssuerCase3() throws Exception { + public void testRemoveAuthorityIssuer_weIdBlank() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.setWeId("di:weid:0x29f3fe8d4536966af41392f7ddc756b6f452df09"); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.setWeId(""); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DId is not exists. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testRemoveAuthorityIssuerCase4() throws Exception { + public void testRemoveAuthorityIssuer_weIdFormat() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.setWeId("did:weid:0x21f3fe8d4536966af41392f7ddc756b6f452df09"); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.setWeId("di:weid:0x29f3fe8d4536966af41392f7ddc756b6f452df09"); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: remove success. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID contains zh. */ @Test - public void testRemoveAuthorityIssuerCase5() throws Exception { + public void testRemoveAuthorityIssuer_weIdContainZh() { - CreateWeIdDataResult createWeId = super.createWeId(); + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.setWeId("中国"); - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + ResponseData response = + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "removeAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: WeIdentity DID is exist but toUpper. + */ + @Test + public void testRemoveAuthorityIssuer_weIdUpper() { + + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.setWeId(createWeIdResult.getWeId().toUpperCase()); ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: WeIdentity DID is not exists. + */ + @Test + public void testRemoveAuthorityIssuer_weIdNotExist() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + String weId = createWeIdResult.getWeId(); + removeAuthorityIssuerArgs + .setWeId(weId.replace(weId.substring(weId.length() - 4, weId.length()), "ffff")); - ResponseData response1 = + ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); - Assert.assertEquals(true, response1.getResult()); + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: remove AuthorityIssuer repeat. + */ + @Test + public void testRemoveAuthorityIssuer_removeRepeat() { + + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = removeAuthoritySuccess(); + Assert.assertNotNull(removeAuthorityIssuerArgs); + + ResponseData response = + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "removeAuthorityIssuer", response); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); } /** - * case: the weIdentity DId is removed. - * - * @throws Exception may be throw Exception + * case: remove success. */ @Test - public void testRemoveAuthorityIssuerCase6() throws Exception { + public void testRemoveAuthorityIssuer_success() { + + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = removeAuthoritySuccess(); + Assert.assertNotNull(removeAuthorityIssuerArgs); + } + private RemoveAuthorityIssuerArgs removeAuthoritySuccess() { CreateWeIdDataResult createWeId = super.createWeId(); RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(response); + ResponseData response = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); + + while (response.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + response = authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId, privateKey); ResponseData response1 = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); + LogUtil.info(logger, "removeAuthorityIssuer", response1); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(true, response1.getResult()); - - response1 = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); - - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), - response1.getErrorCode().intValue()); - Assert.assertEquals(false, response1.getResult()); + return removeAuthorityIssuerArgs; } /** - * case: the weIdentity DId is register by other. - * - * @throws Exception may be throw Exception + * case: the WeIdentity DID is removed. */ @Test - public void testRemoveAuthorityIssuerCase7() throws Exception { + public void testRemoveAuthorityIssuer_weIdIsRemoved() { - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.setWeId("did:weid:0x5f3d8234e93823fac7ebdf0cfaa03b6a43d8773b"); + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = removeAuthoritySuccess(); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); @@ -232,18 +235,13 @@ public void testRemoveAuthorityIssuerCase7() throws Exception { /** * case: removeAuthorityIssuerArgs is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRemoveAuthorityIssuerCase8() throws Exception { - - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = null; + public void testRemoveAuthorityIssuer_issuerArgsIsNull() { ResponseData response = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + authorityIssuerService.removeAuthorityIssuer(null); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); @@ -251,20 +249,17 @@ public void testRemoveAuthorityIssuerCase8() throws Exception { /** * case: weIdPrivateKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRemoveAuthorityIssuerCase9() throws Exception { + public void testRemoveAuthorityIssuer_priKeyNull() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); removeAuthorityIssuerArgs.setWeIdPrivateKey(null); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), response.getErrorCode().intValue()); @@ -273,20 +268,17 @@ public void testRemoveAuthorityIssuerCase9() throws Exception { /** * case: privateKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testRemoveAuthorityIssuerCase10() throws Exception { + public void testRemoveAuthorityIssuer_setPriKeyNull() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(null); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), response.getErrorCode().intValue()); @@ -294,205 +286,135 @@ public void testRemoveAuthorityIssuerCase10() throws Exception { } /** - * case: privateKey is invalid. - * - * @throws Exception may be throw Exception + * case: weIdPrivateKey is blank. */ @Test - public void testRemoveAuthorityIssuerCase11() throws Exception { + public void testRemoveAuthorityIssuer_priKeyBlank() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey("xxxxxxx"); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(""); + removeAuthorityIssuerArgs.setWeIdPrivateKey(weIdPrivateKey); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey belongs to the private key of other weIdentity DId. - * - * @throws Exception may be throw Exception + * case: privateKey is invalid. */ @Test - public void testRemoveAuthorityIssuerCase12() throws Exception { - - CreateWeIdDataResult createWeId = super.createWeId(); - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - - ResponseData responseRegister = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(responseRegister); + public void testRemoveAuthorityIssuer_invalidPriKey() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey("123~!@#$<>?-+sz中国"); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode(), + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey and private key of weIdentity DId do not match. - * - * @throws Exception may be throw Exception + * case: privateKey is valid,but not the sdk admin. */ @Test - public void testRemoveAuthorityIssuerCase13() throws Exception { - - CreateWeIdDataResult createWeId = super.createWeId(); - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = - TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId); - - ResponseData responseRegist = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - System.out.println("\nregisterAuthorityIssuer result:"); - BeanUtil.print(responseRegist); + public void testRemoveAuthorityIssuer_noPermission() { RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - removeAuthorityIssuerArgs.getWeIdPrivateKey() - .setPrivateKey(TestBaseUtil.createEcKeyPair()[1]); + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeIdResult, privateKey); + String badPrikey = privateKey.substring(0, privateKey.length() - 2); + removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(badPrikey); ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("removeAuthorityIssuer result:"); - BeanUtil.print(response); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NO_PERMISSION.getCode(), + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: mock an InterruptedException. - * - * @throws Exception may be throw Exception + * case: privateKey belongs to the private key of other WeIdentity DID. */ @Test - public void testRemoveAuthorityIssuerCase14() throws Exception { + public void testRemoveAuthorityIssuerCase12() { - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); + CreateWeIdDataResult createWeId = super.createWeId(); - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); - MockUp mockTest = new MockUp() { - @Mock - public Future removeAuthorityIssuer(Address addr) throws Exception { + ResponseData responseRegister = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); - return mockFuture.getMockInstance(); - } - }; + while (responseRegister.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + responseRegister = authorityIssuerService + .registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", responseRegister); - ResponseData response1 = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); + RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId, privateKey); + removeAuthorityIssuerArgs.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - mockTest.tearDown(); - mockFuture.tearDown(); + ResponseData response = + authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response1.getErrorCode().intValue()); - Assert.assertEquals(false, response1.getResult()); + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); } /** - * case: mock an TimeoutException. - * - * @throws Exception may be throw Exception + * case: privateKey and private key of WeIdentity DID do not match. */ @Test - public void testRemoveAuthorityIssuerCase15() throws Exception { - - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future removeAuthorityIssuer(Address addr) throws Exception { - - return mockFuture.getMockInstance(); - } - }; + public void testRemoveAuthorityIssuerCase13() { - ResponseData response1 = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); + CreateWeIdDataResult createWeId = super.createWeId(); - mockTest.tearDown(); - mockFuture.tearDown(); + RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = + TestBaseUtil.buildRegisterAuthorityIssuerArgs(createWeId, privateKey); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response1.getErrorCode().intValue()); - Assert.assertEquals(false, response1.getResult()); - } + ResponseData responseRegister = new ResponseData<>(false, + ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS); - /** - * case: mock returns null when invoking the getAuthorityIssuerRetLogEvents. - * - * @throws Exception may be throw Exception - */ - @Test - public void testRemoveAuthorityIssuerCase16() throws Exception { + while (responseRegister.getErrorCode() + == ErrorCode.AUTHORITY_ISSUER_CONTRACT_ERROR_NAME_ALREADY_EXISTS.getCode()) { + String name = registerAuthorityIssuerArgs.getAuthorityIssuer().getName(); + registerAuthorityIssuerArgs.getAuthorityIssuer().setName(name + Math.random()); + responseRegister = authorityIssuerService + .registerAuthorityIssuer(registerAuthorityIssuerArgs); + } + LogUtil.info(logger, "registerAuthorityIssuer", responseRegister); RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = - TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId); - - MockUp mockTest = new MockUp() { - @Mock - public List getAuthorityIssuerRetLogEvents( - TransactionReceipt transactionReceipt) { - List list = - new ArrayList(); - list.add(null); - return list; - } - }; + TestBaseUtil.buildRemoveAuthorityIssuerArgs(createWeId, privateKey); + removeAuthorityIssuerArgs.getWeIdPrivateKey() + .setPrivateKey(TestBaseUtil.createEcKeyPair().getPrivateKey()); - ResponseData response1 = + ResponseData response = authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - System.out.println("\nremoveAuthorityIssuer result:"); - BeanUtil.print(response1); - - mockTest.tearDown(); + LogUtil.info(logger, "removeAuthorityIssuer", response); - Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_ERROR.getCode(), - response1.getErrorCode().intValue()); - Assert.assertEquals(false, response1.getResult()); + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); } } diff --git a/src/test/java/com/webank/weid/full/auth/TestRemoveIssuerFromIssuerType.java b/src/test/java/com/webank/weid/full/auth/TestRemoveIssuerFromIssuerType.java new file mode 100644 index 00000000..9ef73bc5 --- /dev/null +++ b/src/test/java/com/webank/weid/full/auth/TestRemoveIssuerFromIssuerType.java @@ -0,0 +1,244 @@ +package com.webank.weid.full.auth; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public class TestRemoveIssuerFromIssuerType extends TestBaseService { + + private static final Logger logger = LoggerFactory + .getLogger(TestRemoveIssuerFromIssuerType.class); + + private static CreateWeIdDataResult createWeId; + + private static CreateWeIdDataResult createWeIdData; + + private String issuerType = null; + + private static CreateWeIdDataResult issuer; + + private static WeIdAuthentication callerAuth = new WeIdAuthentication(); + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.registerAuthorityIssuer(); + } + if (createWeIdData == null) { + createWeIdData = super.createWeId(); + } + if (issuerType == null) { + issuerType = super.registerIssuerType("rockyXia"); + } + } + + /** + * add issuer into issuer type. + */ + @Before + public void andIssuerIntoIssuerType() { + callerAuth.setWeId(createWeId.getWeId()); + callerAuth.setAuthenticationMethodId(createWeId.getUserWeIdPublicKey().getPublicKey()); + callerAuth.setWeIdPrivateKey(createWeId.getUserWeIdPrivateKey()); + authorityIssuerService.recognizeAuthorityIssuer(createWeId.getWeId(), + new WeIdPrivateKey(privateKey)); + + issuer = super.createWeId(); + ResponseData response = authorityIssuerService + .addIssuerIntoIssuerType(callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "addIssuerIntoIssuerType", response); + } + + /** + * remove issuer from issuer type. + */ + @After + public void removeIssuerFromIssuerType() { + callerAuth.setWeId(createWeId.getWeId()); + callerAuth.setAuthenticationMethodId(createWeId.getUserWeIdPublicKey().getPublicKey()); + callerAuth.setWeIdPrivateKey(createWeId.getUserWeIdPrivateKey()); + + ResponseData res = authorityIssuerService + .removeIssuerFromIssuerType(callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + + /** + * case:callerAuth is not authorityIssuer . + */ + @Test + public void testRemoveIssuerFromIssuerType_notAuthIssuer() { + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(createWeIdData); + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:callerAuth weId not match private key. + */ + @Test + public void testRemoveIssuerFromIssuerType_callerAuthPriKeyNotMatch() { + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(createWeId); + final WeIdPrivateKey key = createWeId.getUserWeIdPrivateKey(); + callerAuth.setWeIdPrivateKey(createWeIdData.getUserWeIdPrivateKey()); + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + callerAuth.setWeIdPrivateKey(key); + Assert.assertEquals(ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:callerAuth is null. + */ + @Test + public void testRemoveIssuerFromIssuerType_callerAuthPriKeyNull() { + + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(createWeId); + final WeIdPrivateKey key = createWeId.getUserWeIdPrivateKey(); + callerAuth.setWeIdPrivateKey(null); + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + callerAuth.setWeIdPrivateKey(key); + + Assert.assertEquals(ErrorCode.AUTHORITY_ISSUER_PRIVATE_KEY_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:callerAuth is null. + */ + @Test + public void testRemoveIssuerFromIssuerType_callerAuthNull() { + WeIdAuthentication callerAuth = new WeIdAuthentication(); + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:issuer type not exist. + */ + @Test + public void testRemoveIssuerFromIssuerType_issuerTypeNotRegister() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, "中国人民-chinese people", issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + + } + + /** + * case:issuer type is null. + */ + @Test + public void testRemoveIssuerFromIssuerType_issuerTypeNull() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, null, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + + } + + /** + * case:issuer type is blank. + */ + @Test + public void testRemoveIssuerFromIssuerType_issuerTypeBlank() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, null, issuer.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:issuer is not in issuer type. + */ + @Test + public void testRemoveIssuerFromIssuerType_issuerNotInIssuerType() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, createWeIdData.getWeId()); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:issuer is not in issuer type. + */ + @Test + public void testRemoveIssuerFromIssuerType_issuerNull() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, null); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } + + /** + * case:invalid issuer. + */ + @Test + public void testRemoveIssuerFromIssuerType_invalidIssuer() { + + ResponseData response = authorityIssuerService.removeIssuerFromIssuerType( + callerAuth, issuerType, "ni!@#$%^&*()-+"); + LogUtil.info(logger, "removeIssuerFromIssuerType", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/auth/TestSpecificIssuer.java b/src/test/java/com/webank/weid/full/auth/TestSpecificIssuer.java new file mode 100644 index 00000000..aca1260f --- /dev/null +++ b/src/test/java/com/webank/weid/full/auth/TestSpecificIssuer.java @@ -0,0 +1,115 @@ + + +package com.webank.weid.full.auth; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.WeIdConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Test most cases of Specific Issuers. + * + * @author chaoxinhu + */ +public class TestSpecificIssuer extends TestBaseService { + + private static String defaultType = "testCollege"; + + @Test + public void integrationSpecificIssuerTest() { + // register an issue type (may already exist) + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthority(createWeIdResult); + ResponseData response1 = + authorityIssuerService.registerIssuerType(weIdAuthentication, defaultType); + Assert.assertTrue(response1.getResult() || (response1.getErrorCode() + == ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode())); + + CreateWeIdDataResult weIdResult = weIdService.createWeId().getResult(); + + // add a WeId as an issuer into it with plain private key + weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(weIdResult.getWeId()); + weIdAuthentication.setWeIdPrivateKey(weIdResult.getUserWeIdPrivateKey()); + ResponseData response2 = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, defaultType, weIdResult.getWeId()); + Assert.assertEquals(response2.getErrorCode().intValue(), + ErrorCode.CONTRACT_ERROR_NO_PERMISSION.getCode()); + + // use the correct (SDK) private key to register + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey().setPrivateKey(privateKey); + ResponseData response3 = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, defaultType, weIdResult.getWeId()); + Assert.assertTrue(response3.getResult()); + + // check the chain to see if this guy is already there + ResponseData response4 = authorityIssuerService + .isSpecificTypeIssuer(defaultType, weIdResult.getWeId()); + Assert.assertTrue(response4.getResult()); + + // remove this WeId + ResponseData response5 = authorityIssuerService + .removeIssuerFromIssuerType(weIdAuthentication, defaultType, weIdResult.getWeId()); + Assert.assertTrue(response5.getResult()); + ResponseData response6 = authorityIssuerService + .isSpecificTypeIssuer(defaultType, weIdResult.getWeId()); + Assert.assertFalse(response6.getResult()); + } + + @Test + public void integrationSpecificIssuerListTest() { + // register an issue type (may already exist) + WeIdAuthentication weIdAuthentication = TestBaseUtil.buildWeIdAuthority(createWeIdResult); + ResponseData response1 = + authorityIssuerService.registerIssuerType(weIdAuthentication, defaultType); + Assert.assertTrue(response1.getResult() || (response1.getErrorCode() + == ErrorCode.SPECIFIC_ISSUER_CONTRACT_ERROR_ALREADY_EXISTS.getCode())); + + CreateWeIdDataResult weIdResult1 = weIdService.createWeId().getResult(); + + weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(weIdResult1.getWeId()); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey().setPrivateKey(privateKey); + ResponseData response2 = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, defaultType, weIdResult1.getWeId()); + Assert.assertTrue(response2.getResult()); + CreateWeIdDataResult weIdResult2 = weIdService.createWeId().getResult(); + ResponseData response3 = authorityIssuerService + .addIssuerIntoIssuerType(weIdAuthentication, defaultType, weIdResult2.getWeId()); + Assert.assertTrue(response3.getResult()); + ResponseData> respData = authorityIssuerService + .getAllSpecificTypeIssuerList(defaultType, 0, 2); + Assert.assertNotNull(respData.getResult()); + // We should be able to fetch at least 2 elements + Assert.assertEquals(respData.getResult().size(), 2); + + // Try to fetch max number of elements and it should not return failure + ResponseData> respData2 = authorityIssuerService + .getAllSpecificTypeIssuerList(defaultType, 999999, + WeIdConstant.MAX_AUTHORITY_ISSUER_LIST_SIZE); + ResponseData> respData3 = authorityIssuerService + .getAllSpecificTypeIssuerList(defaultType, 0, + WeIdConstant.MAX_AUTHORITY_ISSUER_LIST_SIZE); + Assert.assertNull(respData2.getResult()); + //Assert.assertEquals(respData2.getResult().size(), 0); + Assert.assertNotNull(respData3.getResult()); + Assert.assertTrue(respData3.getResult().size() > 0); + ResponseData response4 = authorityIssuerService + .removeIssuerFromIssuerType(weIdAuthentication, defaultType, weIdResult1.getWeId()); + ResponseData response5 = authorityIssuerService + .removeIssuerFromIssuerType(weIdAuthentication, defaultType, weIdResult2.getWeId()); + Assert.assertTrue(response4.getResult()); + Assert.assertTrue(response5.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/cache/TestCacheManager.java b/src/test/java/com/webank/weid/full/cache/TestCacheManager.java new file mode 100644 index 00000000..6c03ea87 --- /dev/null +++ b/src/test/java/com/webank/weid/full/cache/TestCacheManager.java @@ -0,0 +1,88 @@ + + +package com.webank.weid.full.cache; + +import com.webank.weid.protocol.cpt.Cpt103; +import org.junit.Assert; +import org.junit.Test; + +import com.webank.weid.exception.WeIdBaseException; +import com.webank.weid.suite.cache.CacheManager; +import com.webank.weid.suite.cache.CacheNode; + +public class TestCacheManager { + + @Test + public void testPutAndGetString() { + CacheNode cacheNode = CacheManager.registerCacheNode("Test", 10000L, 100); + String value = "abc"; + cacheNode.put("string", value); + String getValue = cacheNode.get("string"); + Assert.assertEquals(value, getValue); + + String newValue = "newAbc"; + cacheNode.put("string", newValue); + + String newGetValue = cacheNode.get("string"); + Assert.assertEquals(newValue, newGetValue); + } + + @Test + public void testRegisterAgain() { + boolean result = false; + try { + CacheManager.registerCacheNode("Test1", 10000L, 100); + CacheManager.registerCacheNode("Test1", 10000L, 100); + result = true; + } catch (WeIdBaseException e) { + result = false; + } + + Assert.assertFalse(result); + } + + @Test + public void testTimeout() throws InterruptedException { + CacheNode cacheNode = CacheManager.registerCacheNode("TestTimeout", 1000L, 100); + String value = "test"; + cacheNode.put("timeout", value); + String getValue = cacheNode.get("timeout"); + Assert.assertEquals(value, getValue); + Thread.sleep(1500); + getValue = cacheNode.get("timeout"); + Assert.assertNull(getValue); + } + + @Test + public void testPutAndGetObject() { + CacheNode cacheNode = CacheManager.registerCacheNode("obj", 10000L, 100); + Cpt103 cpt = new Cpt103(); + cpt.setId("123456789"); + cacheNode.put("cpt103", cpt); + Cpt103 getObj = cacheNode.get("cpt103"); + Assert.assertTrue(cpt.equals(getObj)); + Assert.assertEquals(cpt.getId(), getObj.getId()); + } + + @Test + public void testMaxNum() throws InterruptedException { + CacheNode cacheNode = CacheManager.registerCacheNode("TestMaxSize", 10000L, 10); + //初始化10个值 + for (int i = 0; i < 10; i++) { + cacheNode.put("key" + i, "value" + i); + } + String value = cacheNode.get("key0"); + Assert.assertEquals("value0", value); + //再次加入一个值 + cacheNode.put("key" + 10, "value" + 10); + //给清除机制缓冲时间 + Thread.sleep(1000); + int count = 0; + for (int i = 0; i <= 10; i++) { + if (cacheNode.get("key" + i) != null) { + count++; + } + } + Assert.assertEquals(10, count); + } +} diff --git a/src/test/java/com/webank/weid/full/console/TestCredentialServiceConsole.java b/src/test/java/com/webank/weid/full/console/TestCredentialServiceConsole.java new file mode 100644 index 00000000..76fef24a --- /dev/null +++ b/src/test/java/com/webank/weid/full/console/TestCredentialServiceConsole.java @@ -0,0 +1,176 @@ +package com.webank.weid.full.console; + +import com.fasterxml.jackson.databind.JsonNode; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.service.console.CredentialServiceConsole; +import com.webank.weid.service.console.WeIdServiceConsole; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +public class TestCredentialServiceConsole { + + private static final Logger logger = LoggerFactory.getLogger(TestCredentialServiceConsole.class); + + private String privateKey = TestBaseUtil.readPrivateKeyFromFile("private_key"); + private static final WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + private static final CredentialServiceConsole credentialServiceConsole = new CredentialServiceConsole(); + private static Integer cptId = 100000; + + /** + * case:when issuer and cpt publisher is same,createCredentialPojo success. + */ + @Test + public void testCreateCredentialPojo_success() { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + weIdAuthentication.setAuthenticationMethodId(WeIdUtils.getWeIdFromPrivateKey(privateKey) + "#keys-0"); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey() + .setPrivateKey(privateKey); + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs.setIssuer(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + createCredentialPojoArgs.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + try { + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + cptJsonSchemaData.put("id", WeIdUtils.getWeIdFromPrivateKey(privateKey)); + createCredentialPojoArgs.setClaim(cptJsonSchemaData); + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + } + createCredentialPojoArgs.setCptId(cptId); + + ResponseData response = + credentialServiceConsole.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(buildCptJsonSchema()); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + if (weIdServiceConsole.queryCpt(cptId).getResult() == null) { + weIdServiceConsole.registerCpt(cptMapArgs, cptId); + } + + ResponseData verify = credentialServiceConsole.verify( + DataToolUtils.publicKeyFromPrivate(new BigInteger(privateKey)).toString(10), response.getResult()); + Assert.assertTrue(verify.getResult()); + + WeIdDocument weIdDocument = weIdServiceConsole.createWeIdDocument(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey))).getResult(); + verify = credentialServiceConsole.verify(weIdDocument, response.getResult()); + Assert.assertTrue(verify.getResult()); + } + + public static HashMap buildCptJsonSchema() { + + HashMap cptJsonSchemaNew = new HashMap(3); + cptJsonSchemaNew.put(JsonSchemaConstant.TITLE_KEY, "Digital Identity"); + cptJsonSchemaNew.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = {"F", "M"}; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap propertitesMap4 = new HashMap(2); + propertitesMap4.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap4.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is weid"); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put("name", propertitesMap1); + cptJsonSchema.put("gender", propertitesMap2); + cptJsonSchema.put("age", propertitesMap3); + cptJsonSchema.put("id", propertitesMap4); + cptJsonSchemaNew.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchema); + + String[] genderRequired = {"id", "name", "gender"}; + cptJsonSchemaNew.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + return cptJsonSchemaNew; + } + + @Test + public void testCreateSelectiveCredential_success() { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + weIdAuthentication.setAuthenticationMethodId(WeIdUtils.getWeIdFromPrivateKey(privateKey) + "#keys-0"); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey() + .setPrivateKey(privateKey); + CreateCredentialPojoArgs> createCredentialPojoArgs = + new CreateCredentialPojoArgs>(); + + createCredentialPojoArgs.setIssuer(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + createCredentialPojoArgs.setExpirationDate( + System.currentTimeMillis() + (1000 * 60 * 60 * 24)); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(buildCptJsonSchema()); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + if (weIdServiceConsole.queryCpt(cptId).getResult() == null) { + weIdServiceConsole.registerCpt(cptMapArgs, cptId); + } + + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + try { + HashMap cptJsonSchemaData = new HashMap(); + JsonNode jsonNode = DataToolUtils.loadJsonObjectFromResource("claim.json"); + cptJsonSchemaData = DataToolUtils.deserialize(jsonNode.toString(), HashMap.class); + cptJsonSchemaData.put("id", WeIdUtils.getWeIdFromPrivateKey(privateKey)); + createCredentialPojoArgs.setClaim(cptJsonSchemaData); + } catch (IOException e) { + logger.error("buildCreateCredentialPojoArgs failed. ", e); + } + createCredentialPojoArgs.setCptId(cptId); + + CredentialPojo credentialPojo = + credentialServiceConsole.createCredential(createCredentialPojoArgs).getResult(); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + CredentialPojo selectiveCredentialPojo = + credentialServiceConsole.createSelectiveCredential(credentialPojo, claimPolicy).getResult(); + + Assert.assertNotNull(selectiveCredentialPojo); + + ResponseData verify = credentialServiceConsole.verify( + DataToolUtils.publicKeyFromPrivate(new BigInteger(privateKey)).toString(10), selectiveCredentialPojo); + LogUtil.info(logger, "selectiveCredentialPojo", selectiveCredentialPojo); + LogUtil.info(logger, "verifyCredentialPojo", verify); + Assert.assertTrue(verify.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/console/TestWeIdServiceConsole.java b/src/test/java/com/webank/weid/full/console/TestWeIdServiceConsole.java new file mode 100644 index 00000000..1ad145a4 --- /dev/null +++ b/src/test/java/com/webank/weid/full/console/TestWeIdServiceConsole.java @@ -0,0 +1,243 @@ +package com.webank.weid.full.console; + +import com.webank.weid.MockIssuerClient; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.constant.ErrorCode; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.full.TestData; +import com.webank.weid.protocol.base.*; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.service.console.WeIdServiceConsole; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class TestWeIdServiceConsole { + + private static final Logger logger = LoggerFactory.getLogger(TestWeIdServiceConsole.class); + + private static final WeIdServiceConsole weIdServiceConsole = new WeIdServiceConsole(); + private String privateKey = TestBaseUtil.readPrivateKeyFromFile("private_key"); + + static { MockIssuerClient.mockMakeCredentialTemplate();} + + /** + * case: create WeIdDocument success. + */ + @Test + public void testCreateWeIdDocument_createSuccess() { + + ResponseData response = weIdServiceConsole.createWeIdDocument(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey))); + LogUtil.info(logger, "createWeIdDocument", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: create WeIdDocument Json success. + */ + @Test + public void testCreateWeIdDocumentJson_createSuccess() { + + ResponseData response = weIdServiceConsole.createWeIdDocumentJson(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey))); + LogUtil.info(logger, "createWeIdDocumentJson", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: create WeIdDocument Metadata Json success. + */ + @Test + public void testCreateWeIdDocumentMetadata_createSuccess() { + + ResponseData response = weIdServiceConsole.createWeIdDocumentMetadata(); + LogUtil.info(logger, "createWeIdDocumentMetadata", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: SetAuthentication success. + */ + @Test + public void testSetAuthentication_setAuthenticationSuccess() { + + WeIdDocument weIdDocument = weIdServiceConsole.createWeIdDocument(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey))).getResult(); + AuthenticationArgs setAuthenticationArgs = new AuthenticationArgs(); + setAuthenticationArgs.setPublicKey(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(DataToolUtils.generatePrivateKey()))); + ResponseData response = weIdServiceConsole.setAuthentication(weIdDocument, setAuthenticationArgs); + LogUtil.info(logger, "createWeIdDocumentJson", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: set success. + */ + @Test + public void testSetService_sucess() { + + ServiceArgs serviceArgs = new ServiceArgs(); + serviceArgs.setType(TestData.SERVICE_TYPE); + serviceArgs.setServiceEndpoint(TestData.SERVICE_ENDPOINT); + + WeIdDocument weIdDocument = weIdServiceConsole.createWeIdDocument(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey))).getResult(); + ResponseData response = weIdServiceConsole.setService(weIdDocument, serviceArgs); + LogUtil.info(logger, "setService", response); + + Assert.assertEquals(com.webank.weid.blockchain.constant.ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + } + + /** + * build cpt json schema. + * + * @return HashMap + */ + public static HashMap buildCptJsonSchema() { + + HashMap cptJsonSchemaNew = new HashMap(3); + cptJsonSchemaNew.put(JsonSchemaConstant.TITLE_KEY, "Digital Identity"); + cptJsonSchemaNew.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + String[] genderEnum = {"F", "M"}; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is age"); + + HashMap propertitesMap4 = new HashMap(2); + propertitesMap4.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap4.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is weid"); + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put("name", propertitesMap1); + cptJsonSchema.put("gender", propertitesMap2); + cptJsonSchema.put("age", propertitesMap3); + cptJsonSchema.put("id", propertitesMap4); + cptJsonSchemaNew.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchema); + + String[] genderRequired = {"id", "name", "gender"}; + cptJsonSchemaNew.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + return cptJsonSchemaNew; + } + + /** + * case: when ctpId bigger>200 000 0,register ordinary cpt success. + */ + @Test + public void testRegisterCptArgsWithId_ordinaryCptSuccess() throws Exception { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey() + .setPrivateKey(privateKey); + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(buildCptJsonSchema()); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + Integer issuerCptId = 2000000; + while (weIdServiceConsole.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = weIdServiceConsole.registerCpt(cptMapArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptId", response); + + Assert.assertEquals(com.webank.weid.blockchain.constant.ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: cpt updateCpt success, used no auth issuer to update no auth cpt. + */ + @Test + public void testUpdateCpt_success() { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey() + .setPrivateKey(privateKey); + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(buildCptJsonSchema()); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + Integer issuerCptId = 10086; + while (weIdServiceConsole.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + weIdServiceConsole.registerCpt(cptMapArgs, issuerCptId); + + ResponseData response = weIdServiceConsole.updateCpt( + cptMapArgs, + issuerCptId); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(com.webank.weid.blockchain.constant.ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + @Test + public void happyPathPolicyAll() { + WeIdAuthentication auth = new WeIdAuthentication(); + auth.setWeId(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + auth.setAuthenticationMethodId(DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey)) + "#keys-0"); + auth.setWeIdPrivateKey(new WeIdPrivateKey(privateKey)); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + List claimPolicyIdList = new ArrayList<>(); + ResponseData registerResp = weIdServiceConsole + .registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + registerResp = weIdServiceConsole + .registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + registerResp = weIdServiceConsole + .registerPolicy(claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + claimPolicyIdList.add(registerResp.getResult()); + ClaimPolicy claimPolicyFromChain = weIdServiceConsole.getClaimPolicy(registerResp.getResult()) + .getResult(); + Assert.assertFalse(StringUtils.isEmpty(claimPolicyFromChain.getFieldsToBeDisclosed())); + System.out.println(claimPolicyFromChain.getFieldsToBeDisclosed()); + ResponseData presentationResp = weIdServiceConsole + .registerPresentationPolicy(claimPolicyIdList, auth); + Assert.assertTrue(presentationResp.getResult() >= 0); + ResponseData getClaimFromPresResp = weIdServiceConsole + .getPresentationPolicy(presentationResp.getResult()); + LogUtil.info(logger, "presentationPolicyE", getClaimFromPresResp); + Assert.assertNotNull(getClaimFromPresResp.getResult()); + System.out.println(DataToolUtils.serialize(getClaimFromPresResp.getResult())); + } +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestGenerateSchema.java b/src/test/java/com/webank/weid/full/cpt/TestGenerateSchema.java new file mode 100644 index 00000000..70d942b6 --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestGenerateSchema.java @@ -0,0 +1,97 @@ +/** + * Copyright 2014-2021 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.webank.weid.full.cpt; + +import com.fasterxml.jackson.databind.JsonNode; +import com.webank.weid.util.DataToolUtils; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +public class TestGenerateSchema { + + +// /** +// * Generate Default CPT Json Schema based on a given class, to support external invocation. +// * +// * @param myClass the CPT ID +// * @return CPT Schema in Json String +// */ +// public static String generateDefaultCptJsonSchema(Class myClass) { +// try { +// com.github.reinert.jjschema.v1.JsonSchemaFactory schemaFactory +// = new com.github.reinert.jjschema.v1.JsonSchemaV4Factory(); +// schemaFactory.setAutoPutDollarSchema(true); +// JsonNode cptSchema = schemaFactory.createSchema(myClass); +// return DataToolUtils.objToJsonStrWithNoPretty(cptSchema); +// } catch (Exception e) { +// return StringUtils.EMPTY; +// } +// } +// +// @Test +// public void testJjschema() throws IOException { +// String Cpt101 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt101.class); +// String Cpt102 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt102.class); +// String Cpt103 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt103.class); +// String Cpt104 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt104.class); +// String Cpt105 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt105.class); +// String Cpt106 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt106.class); +// String Cpt107 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt107.class); +// String Cpt108 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt108.class); +// String Cpt109 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt109.class); +// String Cpt110 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt110.class); +// String Cpt111 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt111.class); +// String Cpt11 = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt11.class); +// String Cpt11Salt = generateDefaultCptJsonSchema( +// com.webank.weid.protocol.cpt.Cpt11Salt.class); +// +// String path = "D:\\projects\\weid\\WeIdentity\\src\\test\\resources\\default_cpt\\"; +// Files.write(Paths.get(path + "Cpt101" + ".json"), Cpt101.getBytes()); +// Files.write(Paths.get(path + "Cpt102" + ".json"), Cpt102.getBytes()); +// Files.write(Paths.get(path + "Cpt103" + ".json"), Cpt103.getBytes()); +// Files.write(Paths.get(path + "Cpt104" + ".json"), Cpt104.getBytes()); +// Files.write(Paths.get(path + "Cpt105" + ".json"), Cpt105.getBytes()); +// Files.write(Paths.get(path + "Cpt106" + ".json"), Cpt106.getBytes()); +// Files.write(Paths.get(path + "Cpt107" + ".json"), Cpt107.getBytes()); +// Files.write(Paths.get(path + "Cpt108" + ".json"), Cpt108.getBytes()); +// Files.write(Paths.get(path + "Cpt109" + ".json"), Cpt109.getBytes()); +// Files.write(Paths.get(path + "Cpt110" + ".json"), Cpt110.getBytes()); +// Files.write(Paths.get(path + "Cpt111" + ".json"), Cpt111.getBytes()); +// Files.write(Paths.get(path + "Cpt11" + ".json"), Cpt11.getBytes()); +// Files.write(Paths.get(path + "Cpt11Salt" + ".json"), Cpt11Salt.getBytes()); +//// StringBuilder sb = new StringBuilder(); +//// sb.append(Cpt101).append("\n").append(Cpt102).append("\n").append(Cpt103).append("\n").append(Cpt104).append("\n").append(Cpt105) +//// .append("\n").append(Cpt106).append("\n").append(Cpt107).append("\n").append(Cpt108).append("\n").append(Cpt109).append("\n").append(Cpt110) +//// .append("\n").append(Cpt111).append("\n").append(Cpt11).append("\n").append(Cpt11Salt); +//// System.out.println(sb.toString()); +// System.out.println("end"); +// } + +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestPolicyServices.java b/src/test/java/com/webank/weid/full/cpt/TestPolicyServices.java new file mode 100644 index 00000000..2933d126 --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestPolicyServices.java @@ -0,0 +1,78 @@ + + +package com.webank.weid.full.cpt; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DataToolUtils; + +/** + * Testing policy services related methods. + * + * @author chaoxinhu + */ + +public class TestPolicyServices extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestQueryCpt.class); + + @Override + public synchronized void testInit() { + + super.testInit(); + if (cptBaseInfo == null) { + cptBaseInfo = super.registerCpt(createWeIdResultWithSetAttr); + } + } + + @Test + public void happyPathPolicyAll() { + WeIdAuthentication auth = new WeIdAuthentication(); + CreateWeIdDataResult cwdr = createWeIdWithSetAttr(); + auth.setWeId(cwdr.getWeId()); + auth.setAuthenticationMethodId(cwdr.getUserWeIdPublicKey().getPublicKey() + "#keys-0"); + auth.setWeIdPrivateKey(cwdr.getUserWeIdPrivateKey()); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + Integer cptId = cptBaseInfo.getCptId(); + ResponseData registerResp = policyService + .registerClaimPolicy(cptId, claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + registerResp = policyService + .registerClaimPolicy(cptId, claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + registerResp = policyService + .registerClaimPolicy(cptId, claimPolicy.getFieldsToBeDisclosed(), auth); + Assert.assertTrue(registerResp.getResult() > 0); + ResponseData> allPoliciesList = policyService + .getAllClaimPolicies(0, 3); + Assert.assertEquals(allPoliciesList.getResult().size(), 3); + System.out.println(DataToolUtils.serialize(allPoliciesList.getResult())); + ClaimPolicy claimPolicyFromChain = policyService.getClaimPolicy(registerResp.getResult()) + .getResult(); + Assert.assertFalse(StringUtils.isEmpty(claimPolicyFromChain.getFieldsToBeDisclosed())); + System.out.println(claimPolicyFromChain.getFieldsToBeDisclosed()); + ResponseData> getClaimFromCptResp = policyService + .getClaimPoliciesFromCpt(cptId); + Assert.assertTrue(getClaimFromCptResp.getResult().size() > 0); + ResponseData presentationResp = policyService + .registerPresentationPolicy(getClaimFromCptResp.getResult(), auth); + Assert.assertTrue(presentationResp.getResult() >= 0); + ResponseData getClaimFromPresResp = policyService + .getPresentationPolicy(presentationResp.getResult()); + Assert.assertNotNull(getClaimFromPresResp.getResult()); + System.out.println(DataToolUtils.serialize(getClaimFromPresResp.getResult())); + } +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestQueryCpt.java b/src/test/java/com/webank/weid/full/cpt/TestQueryCpt.java index c50539d5..b5e1b041 100644 --- a/src/test/java/com/webank/weid/full/cpt/TestQueryCpt.java +++ b/src/test/java/com/webank/weid/full/cpt/TestQueryCpt.java @@ -1,197 +1,133 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.cpt; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.CptController; -import com.webank.weid.full.TestBaseServcie; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; import com.webank.weid.protocol.base.Cpt; import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.request.UpdateCptArgs; -import com.webank.weid.protocol.response.ResponseData; -import java.util.List; -import java.util.concurrent.Future; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Type; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * queryCpt method for testing CptService. - * - * @author v_wbgyang * + * @author v_wbgyang/rockyxia */ -public class TestQueryCpt extends TestBaseServcie { +public class TestQueryCpt extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestQueryCpt.class); @Override - public void testInit() throws Exception { + public synchronized void testInit() { super.testInit(); if (cptBaseInfo == null) { - cptBaseInfo = super.registerCpt(createWeIdWithSetAttr); + cptBaseInfo = super.registerCpt(createWeIdResultWithSetAttr); } } - /** + /** * case: cpt query success . */ @Test - public void testQueryCptCase1() { + public void testQueryCpt_success() { ResponseData response = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryCpt", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } - /** + /** * case: cptId is null. */ @Test - public void testQueryCptCase2() { + public void testQueryCpt_cptIdNull() { ResponseData response = cptService.queryCpt(null); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryCpt", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is minus number. */ @Test - public void testQueryCptCase3() { + public void testQueryCpt_minusCptId() { ResponseData response = cptService.queryCpt(-1); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryCpt", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is not exists. */ @Test - public void testQueryCptCase4() { + public void testQueryCpt_cptIdNotExist() { - ResponseData response = cptService.queryCpt(100000); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.queryCpt(999999999); + LogUtil.info(logger, "queryCpt", response); Assert.assertEquals(ErrorCode.CPT_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** + * case: cptId is too big. + */ + @Test + public void testQueryCpt_cptIdBigger() { + + ResponseData response = cptService.queryCpt(-999999999); + LogUtil.info(logger, "queryCpt", response); + + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** * case: query after updateCpt. */ @Test - public void testQueryCptCase5() { + public void testQueryCpt_afterUpdate() { ResponseData response = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); + LogUtil.info(logger, "queryCpt", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); - UpdateCptArgs updateCptArgs = TestBaseUtil.buildUpdateCptArgs(createWeIdNew, cptBaseInfo); + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); - ResponseData responseUp = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(responseUp); + ResponseData responseUp = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", responseUp); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseUp.getErrorCode().intValue()); Assert.assertNotNull(responseUp.getResult()); ResponseData responseQ = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(responseQ); + LogUtil.info(logger, "queryCpt", responseQ); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseQ.getErrorCode().intValue()); Assert.assertNotNull(responseQ.getResult()); } - /** - * case: mock an InterruptedException. - */ - @Test - public void testQueryCptCase6() { - - final MockUp>>> mockFuture = new MockUp>>>() { - @Mock - public Future>> get() throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future>> queryCpt(Uint256 cptId) throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: mock returns null. - */ - @Test - public void testQueryCptCase7() { - - MockUp mockTest = new MockUp() { - @Mock - public Future>> queryCpt(Uint256 cptId) throws Exception { - return null; - } - }; - - ResponseData response = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } } diff --git a/src/test/java/com/webank/weid/full/cpt/TestRegisterCpt.java b/src/test/java/com/webank/weid/full/cpt/TestRegisterCpt.java deleted file mode 100644 index e3445d69..00000000 --- a/src/test/java/com/webank/weid/full/cpt/TestRegisterCpt.java +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.full.cpt; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.CptController; -import com.webank.weid.contract.CptController.RegisterCptRetLogEventResponse; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.full.TestData; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.util.WeIdUtils; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Assert; -import org.junit.Test; - -/** - * registerCpt method for testing CptService. - * - * @author v_wbgyang - * - */ -public class TestRegisterCpt extends TestBaseServcie { - - private static CreateWeIdDataResult createWeId = null; - - @Override - public void testInit() throws Exception { - - super.testInit(); - if (createWeId == null) { - createWeId = super.createWeId(); - super.registerAuthorityIssuer(createWeId); - } - } - - /** - * case: cpt register success. - */ - @Test - public void testRegisterCptCase1() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); - } - - /** - * case: registerCptArgs is null. - */ - @Test - public void testRegisterCptCase2() { - - ResponseData response = cptService.registerCpt(null); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptJsonSchema is null. - */ - @Test - public void testRegisterCptCase3() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptJsonSchema(null); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptJsonSchema is invalid. - */ - @Test - public void testRegisterCptCase4() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptJsonSchema("xxxxxxxxx"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptJsonSchema too long. - */ - @Test - public void testRegisterCptCase5() throws JsonProcessingException, IOException { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - StringBuffer value = new StringBuffer(""); - for (int i = 0; i < 5000; i++) { - value.append("x"); - } - - JsonNode jsonNode = new ObjectMapper().readTree(TestData.schema); - ObjectNode objNode = (ObjectNode) jsonNode; - objNode.put("title", value.toString()); - String afterStr = - new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(objNode); - - registerCptArgs.setCptJsonSchema(afterStr); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptPublisher is blank. - */ - @Test - public void testRegisterCptCase6() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptPublisher(null); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptPublisher is invalid. - */ - @Test - public void testRegisterCptCase7() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptPublisher("di:weid:0xaaaaaaaaaaaaaaaa"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptPublisher is not exists and the private key does not match. - */ - @Test - public void testRegisterCptCase8() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptPublisher("did:weid:0xaaaaaaaaaaaaaaaa"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cpt register again. - */ - @Test - public void testRegisterCptCase9() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); - - response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); - } - - /** - * case: cptPublisherPrivateKey is null. - */ - @Test - public void testRegisterCptCase10() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptPublisherPrivateKey(null); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: privateKey is null. - */ - @Test - public void testRegisterCptCase11() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey(null); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: privateKey is invalid. - */ - @Test - public void testRegisterCptCase12() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey("1231325456468789"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: privateKey is new privateKey. - * - * @throws Exception may be throw Exception - */ - @Test - public void testRegisterCptCase13() throws Exception { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.getCptPublisherPrivateKey() - .setPrivateKey(TestBaseUtil.createEcKeyPair()[1]); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: privateKey is SDK privateKey. - */ - @Test - public void testRegisterCptCase14() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey(TestBaseUtil.privKey); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: privateKey is xxxxxxxxx. - */ - @Test - public void testRegisterCptCase15() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey("xxxxxxxxxx"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: cptPublisher is not exists and the private key does match. - * - * @throws Exception may be throw Exception - */ - @Test - public void testRegisterCptCase16() throws Exception { - - String[] pk = TestBaseUtil.createEcKeyPair(); - String weId = WeIdUtils.convertPublicKeyToWeId(pk[0]); - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - registerCptArgs.setCptPublisher(weId); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey(pk[1]); - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: mock an InterruptedException. - */ - @Test - public void testRegisterCptCase17() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future registerCpt( - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: mock an TimeoutException. - */ - @Test - public void testRegisterCptCase18() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future registerCpt( - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: mock returns null. - */ - @Test - public void testRegisterCptCase19() { - - RegisterCptArgs registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeId); - - MockUp mockTest = new MockUp() { - @Mock - public List getRegisterCptRetLogEvents( - TransactionReceipt transactionReceipt) { - return null; - } - }; - - ResponseData response = cptService.registerCpt(registerCptArgs); - System.out.println("\nregisterCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } -} diff --git a/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgs.java b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgs.java new file mode 100644 index 00000000..d9bd0ff5 --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgs.java @@ -0,0 +1,587 @@ + + +package com.webank.weid.full.cpt; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.Cpt; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.WeIdUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; + +/** + * registerCpt(CptMapArgs args) method for testing CptService. + * + * @author v_wbgyang. + */ +public class TestRegisterCptArgs extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestRegisterCptArgs.class); + + private static CreateWeIdDataResult createWeId = null; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.createWeId(); + super.registerAuthorityIssuer(createWeId); + authorityIssuerService + .recognizeAuthorityIssuer(createWeId.getWeId(), new WeIdPrivateKey(privateKey)); + } + } + + /** + * case: cpt register success and query sucess. + */ + @Test + public void testRegisterCpt_success() { + + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + + ResponseData response = cptService.registerCpt(registerCptArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + CptBaseInfo cptBaseInfo = response.getResult(); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() > 1000); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() < 300000); + + Integer cptId = cptBaseInfo.getCptId(); + ResponseData reponse = cptService.queryCpt(cptId); + } + + /** + * case: weId who has not register auth issuer register cpt success and query sucess. + */ + @Test + public void testRegisterCpt_weIdNotAuthIssuer() { + + ResponseData isAuthIssuer = authorityIssuerService + .isAuthorityIssuer(createWeIdNew.getWeId()); + Assert.assertFalse(isAuthIssuer.getResult()); + + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeIdNew); + + ResponseData response = cptService.registerCpt(registerCptArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + CptBaseInfo cptBaseInfo = response.getResult(); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() > 2000000); + } + + /** + * case: cpt register success and query sucess. + */ + @Test + public void testRegisterCpt_buildDemoSuccess() { + + HashMap cptJsonSchema = new HashMap(3); + cptJsonSchema.put("标题", "cpt template"); + cptJsonSchema.put("描述", "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(2); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put("描述", "this is name"); + + String[] genderEnum = {"女性", "男性"}; + HashMap propertitesMap2 = new HashMap(2); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put("描述", "this is age"); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = {"name", "gender"}; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeId.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeId.getUserWeIdPrivateKey()); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(registerCptArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + CptBaseInfo cptBaseInfo = response.getResult(); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() > 1000); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() < 3000000); + } + + /** + * case: cptPublisher is not exists and the private key does not match. + */ + @Test + public void testRegisterCpt_weIdNotExist() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication() + .setWeId("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: registerCptArgs is null. + */ + @Test + public void testRegisterCpt_CptArgsNull() { + + CptMapArgs cptMapArgs = null; + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptJsonSchema is null. + */ + @Test + public void testRegisterCpt_cptJsonSchemaNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.setCptJsonSchema(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptJsonSchema is null. + */ + @Test + public void testRegisterCpt_cptJsonSchemaMapNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.setCptJsonSchema(new HashMap<>()); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptJsonSchema is a map. + */ + @Test + public void testRegisterCpt_cptJsonSchema() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + HashMap cptJsonSchema = new HashMap<>(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptJsonSchema.put("name", "rocky xia is good man"); + cptJsonSchema.put("年龄", 18); + cptJsonSchema.put("account", 192.5); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + Integer cptId = response.getResult().getCptId(); + ResponseData res = cptService.queryCpt(cptId); + LogUtil.info(logger, "queryCpt", response); + + Assert.assertEquals(18, res.getResult().getCptJsonSchema().get("年龄")); + } + + /** + * case: cptJsonSchema nest cptJsonSchema. + */ + @Test + public void testRegisterCpt_cptJsonSchemaNestAndSerial() { + + HashMap cptJsonSchema = new HashMap(); + cptJsonSchema.put("标题", "cpt template"); + cptJsonSchema.put("描述", "this is a cpt template"); + + HashMap propertitesMap1 = new HashMap(); + propertitesMap1.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap1.put("描述", "this is name"); + + String[] genderEnum = {"女性", "男性"}; + HashMap propertitesMap2 = new HashMap(); + propertitesMap2.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap2.put(JsonSchemaConstant.DATA_TYPE_ENUM, genderEnum); + + HashMap propertitesMap3 = new HashMap(2); + propertitesMap3.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_NUMBER); + propertitesMap3.put("描述", "this is age"); + propertitesMap3.put("description", propertitesMap2); + + HashMap cptJsonSchemaKeys = new HashMap(3); + cptJsonSchemaKeys.put("name", propertitesMap1); + cptJsonSchemaKeys.put("gender", propertitesMap2); + cptJsonSchemaKeys.put("age", propertitesMap3); + cptJsonSchema.put(JsonSchemaConstant.PROPERTIES_KEY, cptJsonSchemaKeys); + + String[] genderRequired = {"name", "gender"}; + cptJsonSchema.put(JsonSchemaConstant.REQUIRED_KEY, genderRequired); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeId.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeId.getUserWeIdPrivateKey()); + + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = cptService.registerCpt(registerCptArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + CptBaseInfo cptBaseInfo = response.getResult(); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() > 1000); + Assert.assertTrue(cptBaseInfo.getCptId().intValue() < 3000000); + + } + + /** + * case: cptJsonSchema too long. + */ + @Test + public void testRegisterCpt_cptJsonSchemaValueIsTooLong() + throws JsonProcessingException, IOException { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + + StringBuffer value = new StringBuffer(""); + for (int i = 0; i < 5000; i++) { + value.append("x"); + } + + HashMap cptJsonSchema = TestBaseUtil.buildCptJsonSchema(); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, value.toString()); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is blank. + */ + @Test + public void testRegisterCpt_cptPublisherNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is blank. + */ + @Test + public void testRegisterCpt_cptPublisherBlank() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(""); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is invalid. + */ + @Test + public void testRegisterCpt_invalidCptPublisher() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId("did:weid:0x!@#$%^&*()-+?.,中国"); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisherPrivateKey is null. + */ + @Test + public void testRegisterCpt_priKeyNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeIdPrivateKey(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is null. + */ + @Test + public void testRegisterCpt_setPriKeyNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisherPrivateKey is null. + */ + @Test + public void testRegisterCpt_priKeyBlank() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(""); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is invalid. + */ + @Test + public void testRegisterCpt_invalidPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey() + .setPrivateKey("123~!@#$%^&*()-+=?》《中国OIU"); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is new privateKey. + */ + @Test + public void testRegisterCpt_newPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey() + .setPrivateKey(TestBaseUtil.createEcKeyPair().getPrivateKey()); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is SDK privateKey. + */ + @Test + public void testRegisterCpt_sdkPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(privateKey); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is not exists and the private key is match. + */ + @Test + public void testRegisterCpt_cptPublisherNotExist() { + + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + String weId = WeIdUtils.convertPublicKeyToWeId(passwordKey.getPublicKey()); + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(weId); + cptMapArgs.getWeIdAuthentication() + .getWeIdPrivateKey() + .setPrivateKey(passwordKey.getPrivateKey()); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string. + */ + @Test + public void testRegisterCptCase20() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: build cpt string, args is null. + */ + @Test + public void testRegisterCptCase21() { + + CptStringArgs cptStringArgs = null; + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string for unkonw_error. + */ + @Test + public void testRegisterCptCase22() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("xxxxx"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string by file. + */ + @Test + public void testRegisterCptCase23() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, true); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: WeIdAuthentication is null. + */ + @Test + public void testRegisterCpt_weIdAuthenticationNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.setWeIdAuthentication(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.WEID_AUTHORITY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: WeIdAuthentication is blank. + */ + @Test + public void testRegisterCpt_weIdAuthenticationBlank() { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + cptMapArgs.setCptJsonSchema(new HashMap<>()); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgsWithId.java b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgsWithId.java new file mode 100644 index 00000000..a00084ba --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptArgsWithId.java @@ -0,0 +1,587 @@ + + +package com.webank.weid.full.cpt; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.WeIdUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Random; + +/** + * registerCpt(CptMapArgs args, Integer cptId) method for testing CptService. + * + * @author v_wbgyang. + */ +public class TestRegisterCptArgsWithId extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestRegisterCptArgsWithId.class); + + private static CreateWeIdDataResult createWeId = null; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.createWeId(); + super.registerAuthorityIssuer(createWeId); + ResponseData responseData = authorityIssuerService + .recognizeAuthorityIssuer(createWeId.getWeId(), new WeIdPrivateKey(privateKey)); + } + } + + /** + * case: when ctpId in [1,999],no permission register cpt. + */ + @Test + public void testRegisterCptArgsWithId_noPermission() { + // The "system" CPT ID + Random rand = new Random(); + Integer keyCptId = rand.nextInt(999) + 1; + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + ResponseData response = cptService.registerCpt(registerCptArgs, keyCptId); + LogUtil.info(logger, "registerCpt", response); + Assert.assertEquals(ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: when ctpId bigger>200 000 0,register ordinary cpt success. + */ + // CI hold: @Test + public void testRegisterCptArgsWithId_ordinaryCptSuccess() throws Exception { + + CreateWeIdDataResult weIdResult = super.createWeId(); + CptMapArgs registerCptArgs = + TestBaseUtil.buildCptArgs(weIdResult); + + Integer issuerCptId = 2000000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: when ctpId in [1000,2000000],but not register Authority Issuer ,then register cpt + * fail. + */ + @Test + public void testRegisterCptArgsWithId_registerCptFail() throws Exception { + + CreateWeIdDataResult weIdResult = super.createWeId(); + CptMapArgs registerCptArgs = + TestBaseUtil.buildCptArgs(weIdResult); + + Integer issuerCptId = 1000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: when ctpid in [1000,2000000],register auth cpt success. + */ + @Test + public void testRegisterCptArgsWithId_registerAuthCptSuccess() throws Exception { + + CptMapArgs registerCptArgs = + TestBaseUtil.buildCptArgs(createWeId); + + Integer issuerCptId = 1000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: when ctpid in [2000000,],register auth cpt success. + */ + @Test + public void testRegisterCptArgsWithId_registerAuthCptFail() throws Exception { + + CptMapArgs registerCptArgs = + TestBaseUtil.buildCptArgs(createWeId); + + Integer issuerCptId = 2000000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 50 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + + /** + * case: register cpt id success. Query multiple times until find an available id, register + * successfully, and retry with an expected failure. + */ + @Test + public void testRegisterCptArgsWithId_repeat() { + Integer cptId = 6000000; + // Add randomness in the next available cpt number - also for faster test cycles + while (cptService.queryCpt(cptId).getResult() != null) { + cptId += (int) (Math.random() * 50 + 1); + } + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + ResponseData response = cptService.registerCpt(registerCptArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + Assert.assertEquals(response.getErrorCode().intValue(), ErrorCode.SUCCESS.getCode()); + Assert.assertNotNull(response.getResult()); + + // do it twice + ResponseData responseData = cptService.registerCpt(registerCptArgs, cptId); + LogUtil.info(logger, "registerCpt", responseData); + Assert.assertEquals(responseData.getErrorCode().intValue(), + ErrorCode.CPT_ALREADY_EXIST.getCode()); + Assert.assertNull(responseData.getResult()); + } + + /** + * case: cptPublisher is not exists and the private key does not match. + */ + @Test + public void testRegisterCptArgsWithId_weIdNotExist() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication() + .setWeId("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"); + + Integer cptId = 50000; + while (cptService.queryCpt(cptId).getResult() != null) { + cptId += (int) (Math.random() * 50 + 1); + } + + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: registerCptArgs is null. + */ + @Test + public void testRegisterCptArgsWithId_CptArgsNull() { + + CptMapArgs cptMapArgs = null; + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptJsonSchema is null. + */ + @Test + public void testRegisterCptArgsWithId_cptJsonSchemaNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.setCptJsonSchema(null); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptJsonSchema is bad format. + */ + @Test + public void testRegisterCptArgsWithId_cptJsonSchema() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + HashMap cptJsonSchema = new HashMap<>(); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + cptJsonSchema.put("name", "rocky xia is good man"); + cptJsonSchema.put("年龄", 18); + cptJsonSchema.put("account", 192.5); + + Integer issuerCptId = 20000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptMapArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: cptJsonSchema too long. + */ + @Test + public void testRegisterCptArgsWithIdCase5() throws JsonProcessingException, IOException { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + + StringBuffer value = new StringBuffer(""); + for (int i = 0; i < 5000; i++) { + value.append("x"); + } + + HashMap cptJsonSchema = TestBaseUtil.buildCptJsonSchema(); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, value.toString()); + cptMapArgs.setCptJsonSchema(cptJsonSchema); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is blank. + */ + @Test + public void testRegisterCptArgsWithId_cptPublisherNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(null); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is blank. + */ + @Test + public void testRegisterCptArgsWithId_cptPublisherBlank() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(""); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is invalid. + */ + @Test + public void testRegisterCptArgsWithId_invalidCptPublisher() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId("did:weid:0x!@#$%^&*()-+?.,中国"); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisherPrivateKey is null. + */ + @Test + public void testRegisterCptArgsWithId_priKeyNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeIdPrivateKey(null); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is null. + */ + @Test + public void testRegisterCptArgsWithId_setPriKeyNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(null); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisherPrivateKey is null. + */ + @Test + public void testRegisterCptArgsWithId_priKeyBlank() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(""); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is invalid. + */ + @Test + public void testRegisterCptArgsWithId_invalidPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey() + .setPrivateKey("123~!@#$%^&*()-+=?》《中国OIU"); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is new privateKey. + */ + @Test + public void testRegisterCptArgsWithId_newPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey() + .setPrivateKey(TestBaseUtil.createEcKeyPair().getPrivateKey()); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: privateKey is SDK privateKey. + */ + @Test + public void testRegisterCptArgsWithId_sdkPriKey() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(privateKey); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptPublisher is not exists and the private key is match. + */ + @Test + public void testRegisterCptArgsWithId_cptPublisherNotExist() { + + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + String weId = WeIdUtils.convertPublicKeyToWeId(passwordKey.getPublicKey()); + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.getWeIdAuthentication().setWeId(weId); + cptMapArgs.getWeIdAuthentication() + .getWeIdPrivateKey() + .setPrivateKey(passwordKey.getPrivateKey()); + + Integer cptId = 50000; + ResponseData response = cptService.registerCpt(cptMapArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: WeIdAuthentication is null. + */ + @Test + public void testRegisterCptArgsWithId_weIdAuthenticationNull() { + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + cptMapArgs.setWeIdAuthentication(null); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.WEID_AUTHORITY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: WeIdAuthentication is blank. + */ + @Test + public void testRegisterCptArgsWithId_weIdAuthenticationBlank() { + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + CptMapArgs cptMapArgs = new CptMapArgs(); + cptMapArgs.setWeIdAuthentication(weIdAuthentication); + cptMapArgs.setCptJsonSchema(new HashMap<>()); + + ResponseData response = cptService.registerCpt(cptMapArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: register cpt id w/ and w/o permission. + */ + @Test + public void testRegisterCptArgsWithIdPermission() { + // The "system" CPT ID + Integer keyCptId = 50; + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + ResponseData response = cptService.registerCpt(registerCptArgs, keyCptId); + LogUtil.info(logger, "registerCpt", response); + Assert.assertEquals(ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + // The authority issuer related cpt ID + Integer issuerCptId = 1200000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + ResponseData responseData = cptService + .registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", responseData); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), responseData.getErrorCode().intValue()); + Assert.assertNotNull(responseData.getResult()); + + ResponseData errResponse = cptService.registerCpt(registerCptArgs, null); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), errResponse.getErrorCode().intValue()); + } + + /** + * case: register cpt id success. Query multiple times until find an available id, register + * successfully, and retry with an expected failure. + */ + @Test + public void testRegisterCptWithIdSuccessAndDuplicate() { + Integer cptId = 6000000; + // Add randomness in the next available cpt number - also for faster test cycles + while (cptService.queryCpt(cptId).getResult() != null) { + cptId += (int) (Math.random() * 50 + 1); + } + CptMapArgs registerCptArgs = TestBaseUtil.buildCptArgs(createWeId); + ResponseData response = cptService.registerCpt(registerCptArgs, cptId); + LogUtil.info(logger, "registerCpt", response); + Assert.assertEquals(response.getErrorCode().intValue(), ErrorCode.SUCCESS.getCode()); + Assert.assertNotNull(response.getResult()); + + // do it twice + ResponseData responseData = cptService.registerCpt(registerCptArgs, cptId); + LogUtil.info(logger, "registerCpt", responseData); + Assert.assertEquals(responseData.getErrorCode().intValue(), + ErrorCode.CPT_ALREADY_EXIST.getCode()); + Assert.assertNull(responseData.getResult()); + } + + /** + * case: register cpt id with string args. + */ + @Test + public void testRegisterCptStringWithId() throws Exception { + Integer issuerCptId = 1000000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + ResponseData responseData = cptService.registerCpt(cptStringArgs, null); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + responseData.getErrorCode().intValue()); + } +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgs.java b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgs.java new file mode 100644 index 00000000..d8422ade --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgs.java @@ -0,0 +1,296 @@ +package com.webank.weid.full.cpt; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.Cpt; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public class TestRegisterCptStringArgs extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestRegisterCptStringArgs.class); + + private static CreateWeIdDataResult createWeId = null; + + @Override + public synchronized void testInit() { + super.testInit(); + if (createWeId == null) { + createWeId = super.createWeId(); + super.registerAuthorityIssuer(createWeId); + authorityIssuerService + .recognizeAuthorityIssuer(createWeId.getWeId(), new WeIdPrivateKey(privateKey)); + } + } + + /** + * case: build cpt string. + */ + @Test + public void testRegisterCptStringArgs_success() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: weId is not auth issuer. + */ + @Test + public void testRegisterCptStringArgs_notAuthIssuer() throws IOException { + + ResponseData isAuthIssuer = authorityIssuerService + .isAuthorityIssuer(createWeIdNew.getWeId()); + if (isAuthIssuer.getResult()) { + createWeIdNew = super.createWeId(); + } + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeIdNew, false); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() > 2000000); + } + + /** + * case: build cpt string, args is null. + */ + @Test + public void testRegisterStringCptArgs_stringCptArgsNull() { + + CptStringArgs cptStringArgs = null; + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaIsStr() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("xxxxx"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaIsBlankMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsStr() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"name\":\"rocky\"}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-int build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsInt() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"age\":18}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-list build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsList() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"peoples\":[\"liBai\",\"dufu\"]}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-list build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsList2() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"peoples\":[\"liBai\",\"dufu\",18]}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string-map build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"peoples\":{\"liBai\":18,\"dufu\":20}}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used nest string-map build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsNestMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema( + "{\"peoples\":{\"liBai\":{\"唐朝\":{\"age\":800}," + + "\"des\":{\"\":\"best one\"}},\"dufu\":{}}}"); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData res = cptService.queryCpt(response.getResult().getCptId()); + LogUtil.info(logger, "registerCpt", res.getResult().toString()); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertNotNull(res.getResult().getCptJsonSchema()); + } + + + /** + * case: build cpt string ,CptJsonSchema is null. + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaNull() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema(null); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string ,CptJsonSchema is blank. + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaBlank() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema(""); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string by file. + */ + @Test + public void testRegisterStringCptArgs_fromFile() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, true); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgsWithId.java b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgsWithId.java new file mode 100644 index 00000000..31845440 --- /dev/null +++ b/src/test/java/com/webank/weid/full/cpt/TestRegisterCptStringArgsWithId.java @@ -0,0 +1,382 @@ +package com.webank.weid.full.cpt; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.Cpt; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public class TestRegisterCptStringArgsWithId extends TestBaseService { + + private static final Logger logger = LoggerFactory + .getLogger(TestRegisterCptStringArgsWithId.class); + + private static CreateWeIdDataResult createWeId = null; + + @Override + public synchronized void testInit() { + + super.testInit(); + if (createWeId == null) { + createWeId = super.createWeId(); + super.registerAuthorityIssuer(createWeId); + authorityIssuerService + .recognizeAuthorityIssuer(createWeId.getWeId(), new WeIdPrivateKey(privateKey)); + } + } + + /** + * case: build cpt string. + */ + // CI hold: @Test + public void testRegisterCptStringArgs_success() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + + Integer issuerCptId = 1000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: when ctpid in [2000000,],register auth cpt Success. + */ + // CI hold: @Test + public void testRegisterCptArgsWithId_registerAuthCptSuccess() throws Exception { + + CptStringArgs registerCptArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + + Integer issuerCptId = 2500000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 50 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: weId is not auth issuer. + */ + @Test + public void testRegisterCptStringArgs_notAuthIssuer() throws IOException { + + ResponseData isAuthIssuer = authorityIssuerService + .isAuthorityIssuer(createWeIdNew.getWeId()); + if (isAuthIssuer.getResult()) { + createWeIdNew = super.createWeId(); + } + + Integer issuerCptId = 2000000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 50 + 1); + } + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeIdNew, false); + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() > 2000000); + } + + @Test + public void testRegisterCptArgsWithId_registerCptFail() throws Exception { + + CreateWeIdDataResult weIdResult = super.createWeId(); + CptStringArgs registerCptArgs = + TestBaseUtil.buildCptStringArgs(weIdResult, false); + + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 50 + 1); + } + + ResponseData response = cptService.registerCpt(registerCptArgs, issuerCptId); + LogUtil.info(logger, "testRegisterCptArgs with cptid", response); + + Assert.assertEquals(ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string, args is null. + */ + @Test + public void testRegisterStringCptArgs_stringCptArgsNull() { + + CptStringArgs cptStringArgs = null; + ResponseData response = cptService.registerCpt(cptStringArgs, 50000); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaIsStr() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("xxxxx"); + ResponseData response = cptService.registerCpt(cptStringArgs, 50000); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaIsBlankMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{}"); + ResponseData response = cptService.registerCpt(cptStringArgs, 50000); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsStr() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"name\":\"rocky\"}"); + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-int build cpt string . + */ + // CI hold: @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsInt() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"age\":18}"); + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-list build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsList() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"peoples\":[\"liBai\",\"dufu\"]}"); + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used string-list build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsList2() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("{\"peoples\":[\"liBai\",\"dufu\",18]}"); + ResponseData response = cptService.registerCpt(cptStringArgs, 50000); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: used string-map build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + cptStringArgs.setCptJsonSchema("{\"peoples\":{\"liBai\":18,\"dufu\":20}}"); + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertTrue(response.getResult().getCptId() < 2000000); + } + + /** + * case: used nest string-map build cpt string . + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaValueIsNestMap() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema( + "{\"peoples\":{\"liBai\":{\"唐朝\":{\"age\":800}," + + "\"des\":{\"\":\"best one\"}},\"dufu\":{}}}"); + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData res = cptService.queryCpt(response.getResult().getCptId()); + LogUtil.info(logger, "registerCpt", res.getResult().toString()); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertNotNull(res.getResult().getCptJsonSchema()); + } + + + /** + * case: build cpt string ,CptJsonSchema is null. + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaNull() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema(null); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string ,CptJsonSchema is blank. + */ + @Test + public void testRegisterStringCptArgs_CptJsonSchemaBlank() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema(""); + ResponseData response = cptService.registerCpt(cptStringArgs); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case: build cpt string by file. + */ + // CI hold: @Test + public void testRegisterStringCptArgs_fromFile() throws IOException { + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, true); + + Integer issuerCptId = 50000; + while (cptService.queryCpt(issuerCptId).getResult() != null) { + issuerCptId += (int) (Math.random() * 10 + 1); + } + + + ResponseData response = cptService.registerCpt(cptStringArgs, issuerCptId); + LogUtil.info(logger, "registerCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/cpt/TestUpdateCpt.java b/src/test/java/com/webank/weid/full/cpt/TestUpdateCpt.java index f316f02f..7ecdf0db 100644 --- a/src/test/java/com/webank/weid/full/cpt/TestUpdateCpt.java +++ b/src/test/java/com/webank/weid/full/cpt/TestUpdateCpt.java @@ -1,557 +1,617 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.cpt; +import java.io.IOException; +import java.util.HashMap; + import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.CptController; -import com.webank.weid.full.TestBaseServcie; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.full.TestData; import com.webank.weid.protocol.base.Cpt; import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.request.UpdateCptArgs; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.CptMapArgs; +import com.webank.weid.protocol.request.CptStringArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; +import com.webank.weid.blockchain.protocol.response.ResponseData; import com.webank.weid.util.WeIdUtils; -import java.io.IOException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Assert; -import org.junit.Test; /** * updateCpt method for testing CptService. - * - * @author v_wbgyang * + * @author v_wbgyang/rockyxia */ -public class TestUpdateCpt extends TestBaseServcie { +public class TestUpdateCpt extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestUpdateCpt.class); @Override - public void testInit() throws Exception { + public synchronized void testInit() { super.testInit(); if (cptBaseInfo == null) { - cptBaseInfo = super.registerCpt(createWeIdWithSetAttr); + cptBaseInfo = super.registerCpt(createWeIdResultWithSetAttr); + Assert.assertTrue(cptBaseInfo.getCptId() > 2000000); } } - /** - * case: cpt updateCpt success. + /** + * case: cpt updateCpt success, used no auth issuer to update no auth cpt. */ @Test - public void testUpdateCptCase1() { + public void testUpdateCpt_success() { CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); - UpdateCptArgs updateCptArgs = TestBaseUtil.buildUpdateCptArgs(createWeId, cptBaseInfo); + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } - /** + /** + * case: cpt updateCpt success, used auth issuer to update no auth cpt. + */ + @Test + public void testUpdateCpt_AuthIssuerUpdateSuccess() { + + CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); + + CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); + + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: used no auth issuer to update no auth cpt. + */ + @Test + public void testUpdateCpt_updateJsonSchema() throws IOException { + + CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); + + CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); + + CptStringArgs cptMapStringArgs + = TestBaseUtil.buildCptStringArgs(createWeId, false); + cptMapStringArgs.setCptJsonSchema("{\"student\":{\"name\":\"rocky\",\"age\":20}}"); + + ResponseData response = cptService.updateCpt( + cptMapStringArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + ResponseData res = cptService.queryCpt(cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", res.getResult().toString()); + + Assert.assertNotNull(res.getResult().getCptJsonSchema().get("student")); + + //update again + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + ResponseData response2 = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response2); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response2.getErrorCode().intValue()); + Assert.assertNotNull(response2.getResult()); + + ResponseData res2 = cptService.queryCpt(cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", res2.getResult().toString()); + + Assert.assertNull(res2.getResult().getCptJsonSchema().get("student")); + + } + + /** + * case:used auth issuer to update no auth cpt. + */ + @Test + public void testUpdateCpt_noAuthIssuerUpdateAuthCptFail() { + + CreateWeIdDataResult createWeId = super.registerAuthorityIssuer(); + authorityIssuerService.recognizeAuthorityIssuer(createWeId.getWeId(), + new WeIdPrivateKey(privateKey)); + CptMapArgs cptMapArgs = TestBaseUtil.buildCptArgs(createWeId); + CptBaseInfo cptBaseInfo = cptService.registerCpt(cptMapArgs).getResult(); + Assert.assertTrue(cptBaseInfo.getCptId() < 2000000); + + CreateWeIdDataResult createWeIdNew = super.createWeId(); + CptMapArgs cptMapArgs1 = TestBaseUtil.buildCptArgs(createWeIdNew); + + ResponseData response = cptService.updateCpt( + cptMapArgs1, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** * case: updateCptArgs is null. */ @Test - public void testUpdateCptCase2() { + public void testUpdateCpt_cptMapAgsNull() { - ResponseData response = cptService.updateCpt(null); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + CptMapArgs cptMapArgs = null; + ResponseData response = cptService.updateCpt(cptMapArgs, 500000); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is null. */ @Test - public void testUpdateCptCase3() { + public void testUpdateCpt_cptIdNull() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptId(null); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt(cptMapArgs, null); + LogUtil.info(logger, "updateCpt", response); - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is minus number. */ @Test - public void testUpdateCptCase4() { + public void testUpdateCpt_minusCptId() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptId(-1); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt(cptMapArgs, -1); + LogUtil.info(logger, "updateCpt", response); - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is not exists. */ @Test - public void testUpdateCptCase5() { + public void testUpdateCpt_cptIdNotExist() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptId(10000); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt(cptMapArgs, 999999999); + LogUtil.info(logger, "updateCpt", response); - Assert.assertEquals(ErrorCode.CPT_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals( + ErrorCode.CPT_NOT_EXISTS.getCode(), + response.getErrorCode().intValue() + ); Assert.assertNull(response.getResult()); } - /** + /** * case: cptJsonSchema is null. */ @Test - public void testUpdateCptCase6() { + public void testUpdateCpt_cptJsonSchemaNull() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptJsonSchema(null); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.setCptJsonSchema(null); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: cptJsonSchema is invalid. - */ - @Test - public void testUpdateCptCase7() { - - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptJsonSchema("xxxxxxxxx"); - - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** + /** * case: cptJsonSchema too long. */ @Test - public void testUpdateCptCase8() throws JsonProcessingException, IOException { + public void testUpdateCpt_cptJsonSchemaTooLong() throws JsonProcessingException, IOException { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); StringBuffer value = new StringBuffer(""); for (int i = 0; i < 5000; i++) { value.append("x"); } - JsonNode jsonNode = new ObjectMapper().readTree(TestData.schema); - ObjectNode objNode = (ObjectNode) jsonNode; - objNode.put("title", value.toString()); - String afterStr = - new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(objNode); - - updateCptArgs.setCptJsonSchema(afterStr); + HashMap cptJsonSchema = TestBaseUtil.buildCptJsonSchema(); + cptJsonSchema.put(JsonSchemaConstant.TITLE_KEY, value.toString()); + cptMapArgs.setCptJsonSchema(cptJsonSchema); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.CPT_JSON_SCHEMA_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptPublisher is blank. */ @Test - public void testUpdateCptCase9() { + public void testUpdateCpt_cptPublisherBlank() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisher(null); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().setWeId(null); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptPublisher is invalid. */ @Test - public void testUpdateCptCase10() { + public void testUpdateCpt_invalidCptPublisher() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisher("di:weid:0xaaaaaaaaaaaaaaaa"); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().setWeId("di:weid:0xaaaaaaaaaaaaaaaa"); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptPublisher is not exists and the private key does not match. */ @Test - public void testUpdateCptCase11() { + public void testUpdateCpt_cptPublisherNotExist() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisher("did:weid:0xaaaaaaaaaaaaaa"); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication() + .setWeId("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); ResponseData responseCpt = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(responseCpt); + LogUtil.info(logger, "queryCpt", responseCpt); } - /** + /** * case: cptPublisherPrivateKey is null. */ @Test - public void testUpdateCptCase12() { + public void testUpdateCptCase_priKeyNull() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisherPrivateKey(null); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().setWeIdPrivateKey(null); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: private Key is null. */ @Test public void testUpdateCptCase13() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey(null); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(null); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey is invalid. */ @Test public void testUpdateCptCase14() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey("123132545646878901"); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey("123132545646878901"); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey is new privateKey. */ @Test - public void testUpdateCptCase15() throws Exception { + public void testUpdateCptCase15() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey(TestBaseUtil.createEcKeyPair()[1]); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey() + .setPrivateKey(TestBaseUtil.createEcKeyPair().getPrivateKey()); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey belongs to SDK. */ @Test - public void testUpdateCptCase16() throws Exception { + public void testUpdateCptCase16() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey(TestBaseUtil.privKey); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey(privateKey); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: privateKey belongs to new weIdentity dId. + /** + * case: privateKey belongs to new WeIdentity DID. */ @Test - public void testUpdateCptCase17() throws Exception { + public void testUpdateCptCase17() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisherPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: privateKey belongs to new weIdentity DId , cptPublisher is a new WeId. - * [TIP] update success,we will deal with the two issue. - * + /** + * case: privateKey belongs to new WeIdentity DID , cptPublisher is a new WeId. [TIP] update + * success,we will deal with the two issue. */ @Test - public void testUpdateCptCase18() throws Exception { - - UpdateCptArgs updateCptArgs = TestBaseUtil.buildUpdateCptArgs(createWeId, cptBaseInfo); - updateCptArgs.setCptPublisher(createWeIdNew.getWeId()); - updateCptArgs.setCptPublisherPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + public void testUpdateCpt_updatePublisher() { + + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResult); + cptMapArgs.getWeIdAuthentication().setWeId(createWeIdNew.getWeId()); + cptMapArgs.getWeIdAuthentication().setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals( + ErrorCode.CPT_NO_PERMISSION.getCode(), + response.getErrorCode().intValue() + ); } - /** + /** * case: privateKey is xxxxxxx. */ @Test - public void testUpdateCptCase19() throws Exception { + public void testUpdateCptCase19() { - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey("xxxxxxxxxx"); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().getWeIdPrivateKey().setPrivateKey("xxxxxxxxxx"); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptPublisher is not exists , but private key matching. */ @Test - public void testUpdateCptCase20() throws Exception { + public void testUpdateCptCase20() { - String[] pk = TestBaseUtil.createEcKeyPair(); - String weId = WeIdUtils.convertPublicKeyToWeId(pk[0]); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + String weId = WeIdUtils.convertPublicKeyToWeId(passwordKey.getPublicKey()); - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - updateCptArgs.setCptPublisher(weId); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey(pk[1]); + CptMapArgs cptMapArgs = + TestBaseUtil.buildCptArgs(createWeIdResultWithSetAttr); + cptMapArgs.getWeIdAuthentication().setWeId(weId); + cptMapArgs.getWeIdAuthentication() + .getWeIdPrivateKey() + .setPrivateKey(passwordKey.getPrivateKey()); - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); + ResponseData response = cptService.updateCpt( + cptMapArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); Assert.assertEquals(ErrorCode.CPT_PUBLISHER_NOT_EXIST.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); ResponseData responseCpt = cptService.queryCpt(cptBaseInfo.getCptId()); - System.out.println("\nqueryCpt result:"); - BeanUtil.print(responseCpt); + LogUtil.info(logger, "updateCpt", responseCpt); } - /** - * case: mock an InterruptedException. + /** + * case: build cpt string. */ @Test - public void testUpdateCptCase21() { - - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future updateCpt( - Uint256 cptId, - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); + public void testUpdateCptCase23() throws IOException { + + CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); + + CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + + ResponseData response = cptService.updateCpt( + cptStringArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: build cpt string, args is null. + */ + @Test + public void testUpdateCptCase24() { + + CptStringArgs cptStringArgs = null; + + ResponseData response = cptService.updateCpt( + cptStringArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: mock an TimeoutException. + /** + * case: build cpt string for unkonw_error. */ @Test - public void testUpdateCptCase22() { - - UpdateCptArgs updateCptArgs = - TestBaseUtil.buildUpdateCptArgs(createWeIdWithSetAttr, cptBaseInfo); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future updateCpt( - Uint256 cptId, - Address publisher, - StaticArray intArray, - StaticArray bytes32Array, - StaticArray jsonSchemaArray, - Uint8 v, - Bytes32 r, - Bytes32 s) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = cptService.updateCpt(updateCptArgs); - System.out.println("\nupdateCpt result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); + public void testUpdateCptCase25() throws IOException { + + CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); + + CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, false); + cptStringArgs.setCptJsonSchema("xxxx"); + + ResponseData response = cptService.updateCpt( + cptStringArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals( + ErrorCode.UNKNOW_ERROR.getCode(), + response.getErrorCode().intValue() + ); Assert.assertNull(response.getResult()); } + + /** + * case: build cpt string by file. + */ + @Test + public void testUpdateCptCase26() throws IOException { + + CreateWeIdDataResult createWeId = super.createWeIdWithSetAttr(); + + CptBaseInfo cptBaseInfo = super.registerCpt(createWeId); + + CptStringArgs cptStringArgs = + TestBaseUtil.buildCptStringArgs(createWeId, true); + + ResponseData response = cptService.updateCpt( + cptStringArgs, + cptBaseInfo.getCptId()); + LogUtil.info(logger, "updateCpt", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + } diff --git a/src/test/java/com/webank/weid/full/credential/TestCreateCredential.java b/src/test/java/com/webank/weid/full/credential/TestCreateCredential.java index 82c33eeb..85512e4e 100644 --- a/src/test/java/com/webank/weid/full/credential/TestCreateCredential.java +++ b/src/test/java/com/webank/weid/full/credential/TestCreateCredential.java @@ -1,374 +1,554 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.credential; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.full.TestBaseServcie; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; import com.webank.weid.protocol.base.CptBaseInfo; import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialWrapper; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; /** * createCredential method for testing CredentialService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestCreateCredential extends TestBaseServcie { +public class TestCreateCredential extends TestBaseService { - @Override - public void testInit() throws Exception { + private static final Logger logger = LoggerFactory.getLogger(TestCreateCredential.class); + @Override + public synchronized void testInit() { super.testInit(); if (cptBaseInfo == null) { - cptBaseInfo = super.registerCpt(createWeIdWithSetAttr); + cptBaseInfo = super.registerCpt(createWeIdResultWithSetAttr); } } - /** - * case:createCredential success. + /** + * case:cptjsonshema and claim is same,createCredential success. */ @Test - public void testCreateCredentialCase1() { + public void testCreateCredential_success() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } - /** - * case: createCredentialArgs is null. + /** + * case:cptjsonshema and claim is same,createCredential success. + */ + @Test + public void testMultiSignedCredential_noSd() { + + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + Credential credential = + credentialService.createCredential(createCredentialArgs).getResult().getCredential(); + Assert.assertTrue(credentialService.verify(credential).getResult()); + List credentialList = new ArrayList<>(); + credentialList.add(credential); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialArgs.setExpirationDate(expirationDate); + Credential tempCredential = + credentialService.createCredential(createCredentialArgs).getResult().getCredential(); + credentialList.add(tempCredential); + CreateWeIdDataResult weId2Result = createWeIdWithSetAttr(); + Credential doubleSignedCredential = + credentialService.addSignature(credentialList, weId2Result.getUserWeIdPrivateKey()) + .getResult(); + Assert.assertNotNull(doubleSignedCredential); + Assert.assertEquals(doubleSignedCredential.getCptId(), + CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT); + Assert.assertEquals(doubleSignedCredential.getExpirationDate(), expirationDate); + ResponseData verifyResp = credentialService.verify(doubleSignedCredential); + System.out.println(verifyResp); + Assert.assertTrue(verifyResp.getResult()); + CreateWeIdDataResult weId3Result = createWeIdWithSetAttr(); + credentialList = new ArrayList<>(); + credentialList.add(doubleSignedCredential); + Credential tripleSignedCredential = + credentialService.addSignature(credentialList, weId3Result.getUserWeIdPrivateKey()) + .getResult(); + System.out.println(DataToolUtils.serialize(tripleSignedCredential)); + Assert.assertNotNull(tripleSignedCredential); + Assert.assertEquals(tripleSignedCredential.getCptId(), + CredentialConstant.CREDENTIAL_EMBEDDED_SIGNATURE_CPT); + Assert.assertEquals(tripleSignedCredential.getExpirationDate(), expirationDate); + verifyResp = credentialService.verify(tripleSignedCredential); + System.out.println(verifyResp); + Assert.assertTrue(verifyResp.getResult()); + } + + /** + * case:when cptjsonschema is different ,createCredential success but verify fail. + */ + @Test + public void testCreateCredential_sampleSuccess() { + + HashMap claim = new HashMap<>(); + claim.put("student", new CptBaseInfo()); + claim.put("name", "李白"); + claim.put("age", 1300); + claim.put("poiet", "桃花潭水深千尺,不及汪伦送我情"); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 6000); + createCredentialArgs.setIssuer(createWeIdResultWithSetAttr.getWeId()); + createCredentialArgs.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), + verify.getErrorCode().intValue()); + } + + /** + * case:when cptJsonSchema and claim is different ,createCredential success but verify fail. + */ + @Test + public void testCreateCredential_claimIsSubsetOfCptJsonSchema() { + + HashMap claim = new HashMap<>(); + claim.put("id", createWeIdResultWithSetAttr.getWeId()); + claim.put("name", "李白"); + claim.put("age", 1300); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 6000); + createCredentialArgs.setIssuer(createWeIdResultWithSetAttr.getWeId()); + createCredentialArgs.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), + verify.getErrorCode().intValue()); + } + + /** + * case:when cptJsonSchema and claim is different ,createCredential success but verify fail. */ @Test - public void testCreateCredentialCase2() { + public void testCreateCredential_cptJsonIsSubsetOfClaim() { + + HashMap claim = new HashMap<>(); + claim.put("id", createWeIdResultWithSetAttr.getWeId()); + claim.put("name", "李白"); + claim.put("age", 1300); + claim.put("gender", "F"); + claim.put("city", "changan"); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 1000 * 60); + createCredentialArgs.setIssuer(createWeIdResultWithSetAttr.getWeId()); + createCredentialArgs.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), verify.getErrorCode().intValue()); + } + + /** + * case:when claim and cptJsonSchema key is same but type of value is different, + * createCredential success but verify fail. + */ + @Test + public void testCreateCredential_claimKeyMatchButTypeDifferent() { + + HashMap claim = new HashMap<>(); + claim.put("id", createWeIdResultWithSetAttr.getWeId()); + claim.put("name", "李白"); + claim.put("age", 1300); + claim.put("gender", "FM"); + + CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); + createCredentialArgs.setClaim(claim); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 6000); + createCredentialArgs.setIssuer(createWeIdResultWithSetAttr.getWeId()); + createCredentialArgs.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - ResponseData response = credentialService.createCredential(null); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), + verify.getErrorCode().intValue()); + } + + /** + * case: createCredentialArgs is null. + */ + @Test + public void testCreateCredential_credentialArgsNull() { + CreateCredentialArgs createCredentialArgs = null; + ResponseData response = credentialService + .createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case:cptId is null. */ @Test - public void testCreateCredentialCase3() { + public void testCreateCredential_cptIdNull() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.setCptId(null); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: cptId is minus number. */ @Test - public void testCreateCredentialCase4() { + public void testCreateCredential_cptIdMinus() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.setCptId(-1); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); } - /** + /** * case: cptId is not exists. */ @Test - public void testCreateCredentialCase5() { + public void testCreateCredential_cptIdNotExist() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setCptId(100000); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setCptId(999999999); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), + verify.getErrorCode().intValue()); } - /** + /** * case: cptId is belongs to others weIdentity dId. */ - @Test - public void testCreateCredentialCase6() { + // CI hold: @Test + public void testCreateCredential_otherCptIdSuccess() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); CptBaseInfo cptBaseInfoNew = super.registerCpt(createWeIdNew); createCredentialArgs.setCptId(cptBaseInfoNew.getCptId()); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + verify.getErrorCode().intValue()); } - /** + /** * case: issuer is null. */ @Test - public void testCreateCredentialCase7() { + public void testCreateCredential_issuerNull() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.setIssuer(null); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: issuer is invalid. */ @Test - public void testCreateCredentialCase8() { + public void testCreateCredential_invalidIssuer() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setIssuer("di:weid:0x1111111111"); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setIssuer("di:weid:0x11!@#$%^&*()_+zhon 中国》《?12qwe"); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: issuer is not exists. + /** + * case: issuer and private key not match. */ @Test - public void testCreateCredentialCase9() { + public void testCreateCredential_priKeyNotMatch() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setIssuer("did:weid:0x1111111111"); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + verify.getErrorCode().intValue()); } - /** - * case: expirationDate <= 0. + /** + * case: private key is sdk private key. */ @Test - public void testCreateCredentialCase10() { + public void testCreateCredential_sdkPriKey() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setExpirationDate(0L); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + createCredentialArgs.setWeIdPrivateKey(weIdPrivateKey); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialService.verify(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + verify.getErrorCode().intValue()); + } + + + /** + * case: test issuance date changes. + */ + @Test + public void createCredentialWithIssuanceDateTest() { + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setIssuanceDate(0L); + ResponseData response = + credentialService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: expirationDate <= now. + /** + * case: expirationDate <= 0. */ @Test - public void testCreateCredentialCase11() { + public void testCreateCredential_expirationDateIsZero() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setExpirationDate(System.currentTimeMillis() - 1000000); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setExpirationDate(0L); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); } - /** - * case: claim is null. + /** + * case: expirationDate <= now. */ @Test - public void testCreateCredentialCase12() { + public void testCreateCredential_expirationDatePassed() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setClaim(null); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() - 1000000); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** - * case: claim is xxxxxxx. + /** + * case: claim is null. */ @Test - public void testCreateCredentialCase13() { + public void testCreateCredential_claimNull() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); - createCredentialArgs.setClaim("xxxxxxxxxxxxxx"); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); + createCredentialArgs.setClaim(null); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertNotNull(response.getResult()); + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); } - /** + /** * case: weIdPrivateKey is null. */ @Test - public void testCreateCredentialCase14() { + public void testCreateCredential_priKeyNull() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.setWeIdPrivateKey(null); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey is null. */ @Test - public void testCreateCredentialCase15() { + public void testCreateCredential_priKeyNull2() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.getWeIdPrivateKey().setPrivateKey(null); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_PRIVATE_KEY_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey is xxxxxxxxxxx. */ @Test - public void testCreateCredentialCase16() { + public void testCreateCredential_invalidPriKey() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.getWeIdPrivateKey().setPrivateKey("xxxxxxxxxx"); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), response.getErrorCode().intValue()); Assert.assertNull(response.getResult()); } - /** + /** * case: privateKey is 11111111111111. */ - @Test - public void testCreateCredentialCase17() { + // CI hold: @Test + public void testCreateCredential_priKeyIsInt() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr, cptBaseInfo); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr, cptBaseInfo); createCredentialArgs.getWeIdPrivateKey().setPrivateKey("11111111111111"); - ResponseData response = + ResponseData response = credentialService.createCredential(createCredentialArgs); - System.out.println("\ncreateCredential result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); diff --git a/src/test/java/com/webank/weid/full/credential/TestGetCredentialHash.java b/src/test/java/com/webank/weid/full/credential/TestGetCredentialHash.java new file mode 100644 index 00000000..db3e5a9f --- /dev/null +++ b/src/test/java/com/webank/weid/full/credential/TestGetCredentialHash.java @@ -0,0 +1,55 @@ + + +package com.webank.weid.full.credential; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import com.webank.weid.constant.CredentialConstant.CredentialProofType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public class TestGetCredentialHash extends TestBaseService { + + @Test + public void testGetCredentialHash_success() { + Credential credential = buildCredential(); + ResponseData response1 = credentialService.getCredentialHash(credential); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); + + credential = buildCredential(); + credential.setIssuer("xxxxxxxxx"); + response1 = credentialService.getCredentialHash(credential); + Assert.assertNotEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response1.getResult()); + } + + private Credential buildCredential() { + Credential credential = new Credential(); + HashMap claim = new HashMap<>(); + claim.put("id", "xxxxxxxxxxxxxx"); + credential.setClaim(claim); + credential.setContext("v1"); + credential.setCptId(Integer.valueOf(1001)); + credential.setExpirationDate(System.currentTimeMillis() + 1000L); + credential.setId(UUID.randomUUID().toString()); + credential.setIssuer("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"); + credential.setIssuanceDate(System.currentTimeMillis()); + Map proof = new HashMap<>(); + proof.put(ParamKeyConstant.PROOF_CREATOR, credential.getIssuer()); + proof.put(ParamKeyConstant.PROOF_CREATED, credential.getIssuanceDate().toString()); + proof.put(ParamKeyConstant.PROOF_TYPE, CredentialProofType.ECDSA.getTypeName()); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, "xxxxxxxxxxx"); + credential.setProof(proof); + return credential; + } +} diff --git a/src/test/java/com/webank/weid/full/credential/TestGetCredentialJson.java b/src/test/java/com/webank/weid/full/credential/TestGetCredentialJson.java new file mode 100644 index 00000000..90d57fb3 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credential/TestGetCredentialJson.java @@ -0,0 +1,76 @@ + + +package com.webank.weid.full.credential; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.CredentialConstant.CredentialProofType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * Testing getCredentialJson method. + * + * @author chaoxinhu + */ +public class TestGetCredentialJson extends TestBaseService { + + @Test + public void testGetCredentialJsonCase1() { + Credential credential = buildCredential(); + ResponseData response1 = credentialService.getCredentialJson(credential); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); + Assert.assertTrue( + response1 + .getResult() + .contains(CredentialConstant.CREDENTIAL_CONTEXT_PORTABLE_JSON_FIELD)); + Assert.assertTrue( + response1 + .getResult() + .contains(CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT)); + + credential = buildCredential(); + credential.setIssuer("xxxxxxxxx"); + response1 = credentialService.getCredentialHash(credential); + Assert.assertNotEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response1.getResult()); + } + + @Test + public void testGetCredentialJsonCase2() { + ResponseData response1 = credentialService.getCredentialJson(null); + Assert.assertNotEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response1.getResult()); + } + + private Credential buildCredential() { + Credential credential = new Credential(); + HashMap claim = new HashMap<>(); + claim.put("id", "xxxxxxxxxxxxx"); + credential.setClaim(claim); + credential.setContext(CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT); + credential.setCptId(Integer.valueOf(1002)); + credential.setExpirationDate(System.currentTimeMillis() + 10000L); + credential.setId(UUID.randomUUID().toString()); + credential.setIssuer("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"); + credential.setIssuanceDate(System.currentTimeMillis()); + Map proof = new HashMap<>(); + proof.put(ParamKeyConstant.PROOF_CREATOR, credential.getIssuer()); + proof.put(ParamKeyConstant.PROOF_CREATED, credential.getIssuanceDate().toString()); + proof.put(ParamKeyConstant.PROOF_TYPE, CredentialProofType.ECDSA.getTypeName()); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, "xxxxxxxxxxx"); + credential.setProof(proof); + return credential; + } +} diff --git a/src/test/java/com/webank/weid/full/credential/TestVerifyCredential.java b/src/test/java/com/webank/weid/full/credential/TestVerifyCredential.java index dd59c64c..0dd9a75e 100644 --- a/src/test/java/com/webank/weid/full/credential/TestVerifyCredential.java +++ b/src/test/java/com/webank/weid/full/credential/TestVerifyCredential.java @@ -1,577 +1,628 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.credential; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.full.TestBaseServcie; +import java.security.SignatureException; +import java.util.Map; + +import mockit.Mock; +import mockit.MockUp; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.webank.weid.util.CredentialUtils.copyCredential; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.full.TestData; import com.webank.weid.protocol.base.CptBaseInfo; import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialWrapper; import com.webank.weid.protocol.base.WeIdDocument; import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; +import com.webank.weid.blockchain.protocol.response.ResponseData; import com.webank.weid.service.impl.WeIdServiceImpl; -import com.webank.weid.util.CredentialUtils; -import mockit.Mock; -import mockit.MockUp; -import org.junit.Assert; -import org.junit.Test; +import com.webank.weid.util.DataToolUtils; /** * verifyCredential method for testing CredentialService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestVerifyCredential extends TestBaseServcie { +public class TestVerifyCredential extends TestBaseService { - private String[] pk = null; + private static final Logger logger = LoggerFactory.getLogger(TestVerifyCredential.class); - @Override - public void testInit() throws Exception { + protected PasswordKey passwordKey = null; + + private static Credential credential = null; + @Override + public synchronized void testInit() { super.testInit(); - pk = TestBaseUtil.createEcKeyPair(); - if (createCredentialArgs == null) { - registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeIdWithSetAttr); - createCredentialArgs = TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); - cptBaseInfo = this.registerCpt(createWeIdWithSetAttr, registerCptArgs); - createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + passwordKey = TestBaseUtil.createEcKeyPair(); + if (credential == null) { + credential = super.createCredential(createCredentialArgs).getCredential(); } } - /** + /** * case: verifyCredential success. */ @Test - public void testVerifyCredentialCase1() throws Exception { - - Credential credential = super.createCredential(createCredentialArgs); + public void testVerifyCredential_success() { ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } - /** + + /** * case: context is null. */ @Test - public void testVerifyCredentialCase2() { + public void testVerifyCredential_contextNull() { - Credential credential = super.createCredential(createCredentialArgs); + String context = credential.getContext(); credential.setContext(null); - ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setContext(context); Assert.assertEquals(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: context is other string. */ @Test - public void testVerifyCredentialCase3() { + public void testVerifyCredential_contentIsOtherString() { - Credential credential = super.createCredential(createCredentialArgs); + String context = credential.getContext(); credential.setContext("xxx"); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setContext(context); + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: cptId is null. + /** + * case: context contain special char. */ - @Test - public void testVerifyCredentialCase4() { + // CI hold: @Test + public void testVerifyCredential_contentContainSpecialChar() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setCptId(null); + String context = credential.getContext(); + credential.setContext("xxx!@#¥%……&*()KL14536987"); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: cptId is minus number. - */ - @Test - public void testVerifyCredentialCase5() { - - Credential credential = super.createCredential(createCredentialArgs); - credential.setCptId(-1); - - ResponseData response = super.verifyCredential(credential); - - Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), + credential.setContext(context); + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: cptId is not exists. + /** + * case: cptId is another with **same** schema. */ @Test - public void testVerifyCredentialCase6() { + public void testVerifyCredential_cptIdAndClaimDifferent() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setCptId(10000); + Integer cptId = credential.getCptId(); + CptBaseInfo cpt = super.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + credential.setCptId(cpt.getCptId()); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), + credential.setCptId(cptId); + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: cptId is another. + /** + * case: cptId is another with **same** schema. */ @Test - public void testVerifyCredentialCase7() { - - Credential credential = super.createCredential(createCredentialArgs); + public void testVerifyCredential_cptIdNull() { - CptBaseInfo cpt = super.registerCpt(createWeIdWithSetAttr, registerCptArgs); - credential.setCptId(cpt.getCptId()); + Integer cptId = credential.getCptId(); + credential.setCptId(null); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setCptId(cptId); + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: id is null. */ @Test - public void testVerifyCredentialCase8() { + public void testVerifyCredential_idNull() { - Credential credential = super.createCredential(createCredentialArgs); + String id = credential.getId(); credential.setId(null); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setId(id); Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: id is another. */ @Test - public void testVerifyCredentialCase9() { + public void testVerifyCredential_otherId() { - Credential credential = super.createCredential(createCredentialArgs); + String id = credential.getId(); credential.setId("xxxxxxxxx"); - ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setId(id); + Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: issuer is null. */ @Test public void testVerifyCredentialCase10() { - Credential credential = super.createCredential(createCredentialArgs); + String issuer = credential.getIssuer(); credential.setIssuer(null); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setIssuer(issuer); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: issuer is xxxxx. */ @Test - public void testVerifyCredentialCase11() { + public void testVerifyCredential_invalidIssuer() { - Credential credential = super.createCredential(createCredentialArgs); + String issuer = credential.getIssuer(); credential.setIssuer("xxxxxxxxxxx"); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setIssuer(issuer); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: issuer is another. */ @Test - public void testVerifyCredentialCase12() { - - Credential credential = super.createCredential(createCredentialArgs); + public void testVerifyCredential_otherIssuer() { + String issuer = credential.getIssuer(); credential.setIssuer(createWeIdNew.getWeId()); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setIssuer(issuer); + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: issuranceDate < = 0. + /** + * case: IssuanceDate < = 0. */ @Test public void testVerifyCredentialCase13() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuranceDate(-1L); + Long issuanceDate = credential.getIssuanceDate(); + credential.setIssuanceDate(-1L); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setIssuanceDate(issuanceDate); + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: issuranceDate > now. + /** + * case: IssuanceDate > now. */ @Test public void testVerifyCredentialCase14() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuranceDate(System.currentTimeMillis() + 100000); + Long issuanceDate = credential.getIssuanceDate(); + credential.setIssuanceDate(System.currentTimeMillis() + 100000); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + credential.setIssuanceDate(issuanceDate); + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: expirationDate <= 0. */ @Test public void testVerifyCredentialCase15() { - Credential credential = super.createCredential(createCredentialArgs); + Long expirationDate = credential.getExpirationDate(); credential.setExpirationDate(-1L); - ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setExpirationDate(expirationDate); Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: expirationDate <= now. */ @Test public void testVerifyCredentialCase16() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setExpirationDate(System.currentTimeMillis() - 10000); - + Long expirationDate = credential.getExpirationDate(); + credential.setExpirationDate(credential.getIssuanceDate() - 100000000); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setExpirationDate(expirationDate); Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: expirationDate is null. */ @Test public void testVerifyCredentialCase17() { - Credential credential = super.createCredential(createCredentialArgs); + Long expirationDate = credential.getExpirationDate(); credential.setExpirationDate(null); - ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setExpirationDate(expirationDate); Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: issuranceDate is null. + /** + * case: IssuanceDate is null. */ @Test public void testVerifyCredentialCase18() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuranceDate(null); - + Long issuanceDate = credential.getIssuanceDate(); + credential.setIssuanceDate(null); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CREATE_DATE_ILLEGAL.getCode(), + credential.setIssuanceDate(issuanceDate); + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: claim is null. + /** + * case: claim is null. test error,Please add check. */ - @Test - public void testVerifyCredentialCase19() { + // @Test + public void testVerifyCredential_claimNull() { - Credential credential = super.createCredential(createCredentialArgs); + Map claim = credential.getClaim(); credential.setClaim(null); - ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setClaim(claim); Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: claim is xxxxxxxxxx. + /** + * case: mock SignatureException. */ - @Test + /*@Test public void testVerifyCredentialCase20() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setClaim("xxxxxxxxxxxxxx"); - + new MockUp() { + @Mock + public Sign.SignatureData simpleSignatureDeserialization( + byte[] serializedSignatureData) throws SignatureException { + throw new SignatureException(); + } + }; ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); - } + }*/ - /** - * case: claim does not match jsonSchema. + /** + * case: signature is empty. */ @Test public void testVerifyCredentialCase21() { + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, StringUtils.EMPTY); + newCredential.setProof(proof); - Credential credential = super.createCredential(createCredentialArgs); - credential.setClaim(TestData.schemaDataInvalid); - - ResponseData response = super.verifyCredential(credential); + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: signature is null. */ @Test public void testVerifyCredentialCase22() { + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, null); + newCredential.setProof(proof); - Credential credential = super.createCredential(createCredentialArgs); - credential.setSignature(null); - - ResponseData response = super.verifyCredential(credential); + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: signature is xxxxxxxxxxxxxxxxxxx. */ @Test public void testVerifyCredentialCase23() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setSignature("xxxxxxxxxxxxxxx"); + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, "xxxxxxxxxxx"); + newCredential.setProof(proof); - ResponseData response = super.verifyCredential(credential); + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), + //Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: signature by 122324324324. */ @Test - public void testVerifyCredentialCase24() throws Exception { + public void testVerifyCredentialCase24() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); createCredentialArgs.getWeIdPrivateKey().setPrivateKey("122324324324"); - Credential credential = super.createCredential(createCredentialArgs); - - ResponseData response = super.verifyCredential(credential); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + ResponseData response = super.verifyCredential(credentialWrapper.getCredential()); + LogUtil.info(logger, "verifyCredential", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: signature by non weIdentity DId publickeys. - */ - @Test - public void testVerifyCredentialCase25() throws Exception { - - CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); - createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - Credential credential = super.createCredential(createCredentialArgs); - - ResponseData response = super.verifyCredential(credential); - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: Sing through another private key in publickeys of weIdentity dId. + /** + * case: Sing through another private key in publickeys of WeIdentity DID. */ - @Test - public void testVerifyCredentialCase26() throws Exception { + // CI hold: @Test + public void testVerifyCredentialCase26() { - super.setPublicKey(createWeIdWithSetAttr, pk[0], createWeIdWithSetAttr.getWeId()); - super.setAuthentication(createWeIdWithSetAttr, pk[0], createWeIdWithSetAttr.getWeId()); + super.setAuthentication( + createWeIdResultWithSetAttr, + passwordKey.getPublicKey(), + createWeIdResultWithSetAttr.getWeId()); CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - Credential credential = super.createCredential(createCredentialArgs); - - ResponseData response = super.verifyCredential(credential); + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(passwordKey.getPrivateKey()); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + ResponseData response = super.verifyCredential(credentialWrapper.getCredential()); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } - /** - * case: issuranceDate < now && expirationDate < now && issuranceDate < expirationDate. + /** + * case: IssuanceDate < now && expirationDate < now && IssuanceDate < expirationDate. */ @Test public void testVerifyCredentialCase27() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuranceDate(System.currentTimeMillis() - 12000); + Long issuanceDate = credential.getIssuanceDate(); + Long expirationDate = credential.getExpirationDate(); + credential.setIssuanceDate(System.currentTimeMillis() - 12000); credential.setExpirationDate(System.currentTimeMillis() - 10000); - ResponseData response = super.verifyCredential(credential); + credential.setIssuanceDate(issuanceDate); + credential.setExpirationDate(expirationDate); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: mock CREDENTIAL_WEID_DOCUMENT_ILLEGAL. */ @Test public void testVerifyCredentialCase28() { - Credential credential = super.createCredential(createCredentialArgs); - - MockUp mockTest = new MockUp() { + new MockUp() { @Mock - public ResponseData getWeIdDocument(String weId) throws Exception { + public ResponseData getWeIdDocument(String weId) { ResponseData response = new ResponseData(); - response.setErrorCode(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL.getCode()); + response.setErrorCode(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL); return response; } }; ResponseData response = super.verifyCredential(credential); - - mockTest.tearDown(); + LogUtil.info(logger, "verifyCredential", response); Assert.assertEquals(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: mock NullPointerException. + /** + * case: proof creator and created are null - this is OK. */ @Test public void testVerifyCredentialCase29() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuranceDate(System.currentTimeMillis() - 12000); - credential.setExpirationDate(System.currentTimeMillis() - 10000); + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.PROOF_CREATOR, null); + newCredential.setProof(proof); - MockUp mockTest = new MockUp() { - @Mock - public CreateCredentialArgs extractCredentialMetadata(Credential arg) throws Exception { - throw new NullPointerException(); - } - }; + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); - ResponseData response = super.verifyCredential(credential); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + Assert.assertEquals(true, response.getResult()); } - /** + /** * case: issuer is not exists. */ @Test public void testVerifyCredentialCase30() { - Credential credential = super.createCredential(createCredentialArgs); - credential.setIssuer("did:weid:0x111111111111111"); + String issuer = credential.getIssuer(); + credential.setIssuer("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797441"); ResponseData response = super.verifyCredential(credential); + LogUtil.info(logger, "verifyCredential", response); + credential.setIssuer(issuer); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_NOT_EXISTS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + + /** + * case: proof type illegal. + */ + @Test + public void testVerifyCredentialCase31() { + + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.PROOF_TYPE, null); + newCredential.setProof(proof); + + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing signature key at all - fail. + */ + @Test + public void testVerifyCredentialCase32() { + + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.remove(ParamKeyConstant.CREDENTIAL_SIGNATURE); + newCredential.setProof(proof); + + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing creator key at all - should be fine. + */ + // CI hold: @Test + public void testVerifyCredentialCase33() { + + Credential newCredential = copyCredential(credential); + Map proof = newCredential.getProof(); + proof.remove(ParamKeyConstant.PROOF_CREATOR); + newCredential.setProof(proof); + + ResponseData response = super.verifyCredential(newCredential); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } } diff --git a/src/test/java/com/webank/weid/full/credential/TestVerifyCredentialWithSpecifiedPubKey.java b/src/test/java/com/webank/weid/full/credential/TestVerifyCredentialWithSpecifiedPubKey.java index 3dc98f7d..73b3ef6f 100644 --- a/src/test/java/com/webank/weid/full/credential/TestVerifyCredentialWithSpecifiedPubKey.java +++ b/src/test/java/com/webank/weid/full/credential/TestVerifyCredentialWithSpecifiedPubKey.java @@ -1,233 +1,151 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.credential; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CredentialWrapper; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.CreateCredentialArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * verifyCredentialWithSpecifiedPubKey method for testing CredentialService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestVerifyCredentialWithSpecifiedPubKey extends TestBaseServcie { +public class TestVerifyCredentialWithSpecifiedPubKey extends TestBaseService { - private String[] pk = null; + private static final Logger logger = + LoggerFactory.getLogger(TestVerifyCredentialWithSpecifiedPubKey.class); - @Override - public void testInit() throws Exception { + protected PasswordKey newPasswordKey = null; + @Override + public synchronized void testInit() { super.testInit(); - pk = TestBaseUtil.createEcKeyPair(); - if (createCredentialArgs == null) { - registerCptArgs = TestBaseUtil.buildRegisterCptArgs(createWeIdWithSetAttr); - createCredentialArgs = TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); - cptBaseInfo = this.registerCpt(createWeIdWithSetAttr, registerCptArgs); - createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - } + newPasswordKey = TestBaseUtil.createEcKeyPair(); } - /** + /** * case: verifyCredentialWithSpecifiedPubKey success. */ @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase1() throws Exception { + public void testVerifyCredentialWithSpecifiedPubKeyCase1() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - - Credential credential = super.createCredential(createCredentialArgs); + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, pk[0]); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(newPasswordKey.getPublicKey()); ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } - /** + /** * case: verifyCredentialWithSpecifiedPubKey fail. */ @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase2() throws Exception { + public void testVerifyCredentialWithSpecifiedPubKeyCase2() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); - Credential credential = super.createCredential(createCredentialArgs); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); - String[] pkNew = TestBaseUtil.createEcKeyPair(); - - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, pkNew[0]); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(passwordKey.getPublicKey()); ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); - Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: verifyCredentialWithSpecifiedPubKey publicKey is null. */ @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase3() throws Exception { + public void testVerifyCredentialWithSpecifiedPubKeyCase3() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - - Credential credential = super.createCredential(createCredentialArgs); + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, null); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, null); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** + /** * case: verifyCredentialArgs is null. */ @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase4() throws Exception { - - VerifyCredentialArgs verifyCredentialArgs = null; + public void testVerifyCredentialWithSpecifiedPubKeyCase4() { + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(newPasswordKey.getPublicKey()); ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); + credentialService.verifyCredentialWithSpecifiedPubKey(null, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } - /** - * case: credential is null. - */ - @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase5() throws Exception { - - CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); - createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - - Credential credential = super.createCredential(createCredentialArgs); - - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, pk[0]); - verifyCredentialArgs.setCredential(null); - - ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: weIdPublicKey is null. - */ - @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase6() throws Exception { - - CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); - createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - - Credential credential = super.createCredential(createCredentialArgs); - - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, pk[0]); - verifyCredentialArgs.setWeIdPublicKey(null); - - ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - /** + /** * case: verifyCredentialWithSpecifiedPubKey publicKey is "xxxxxxxxxxxxx". */ @Test - public void testVerifyCredentialWithSpecifiedPubKeyCase7() throws Exception { + public void testVerifyCredentialWithSpecifiedPubKeyCase7() { CreateCredentialArgs createCredentialArgs = - TestBaseUtil.buildCreateCredentialArgs(createWeIdWithSetAttr); + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); createCredentialArgs.setCptId(cptBaseInfo.getCptId()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); - Credential credential = super.createCredential(createCredentialArgs); + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); - VerifyCredentialArgs verifyCredentialArgs = - TestBaseUtil.buildVerifyCredentialArgs(credential, "xxxxxxxxxxxxx"); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey("xxxxxxxxxxxxx"); ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - System.out.println("\nverifyCredentialWithSpecifiedPubKey result:"); - BeanUtil.print(response); + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), response.getErrorCode().intValue()); diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestCreateCredentialPojo.java b/src/test/java/com/webank/weid/full/credentialpojo/TestCreateCredentialPojo.java new file mode 100644 index 00000000..e8438984 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestCreateCredentialPojo.java @@ -0,0 +1,997 @@ + + +package com.webank.weid.full.credentialpojo; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.fisco.bcos.sdk.abi.datatypes.Address; +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.utils.Numeric; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.CredentialType; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.cpt.Cpt101; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.CptStringArgs; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.protocol.request.CreateWeIdArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.CredentialPojoUtils; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; +import com.webank.weid.util.WeIdUtils; + +/** + * createCredential method for testing CredentialService. + * + * @author v_wbgyang + */ +public class TestCreateCredentialPojo extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestCreateCredentialPojo.class); + + @Override + public synchronized void testInit() { + + super.testInit(); + if (cptBaseInfo == null) { + cptBaseInfo = super.registerCpt(createWeIdResultWithSetAttr); + Assert.assertTrue(cptBaseInfo.getCptId() > 2000000); + } + } + + /** + * case:when issuer and cpt publisher is same,createCredentialPojo success. + */ + @Test + public void testCreateCredentialPojo_success() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertTrue(verify.getResult()); + } + + @Test + public void testCreateCredentialPojoWithOtherWeIdAndRevocation_success() { + CreateWeIdDataResult cwdr = createWeIdWithSetAttr(); + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuer(cwdr.getWeId()); + WeIdAuthentication weIdAuth = new WeIdAuthentication(); + weIdAuth.setWeId(cwdr.getWeId()); + + // Add new public key to this guy + PasswordKey pwKey = TestBaseUtil.createEcKeyPair(); + AuthenticationArgs arg = new AuthenticationArgs(); + arg.setController(cwdr.getWeId()); + arg.setPublicKey(pwKey.getPublicKey()); + ResponseData addResp = weIdService.setAuthentication(cwdr.getWeId(), + arg, cwdr.getUserWeIdPrivateKey()); + System.out.println(weIdService.getWeIdDocumentJson(cwdr.getWeId())); + + // Using the new private key to sign credential + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(pwKey.getPrivateKey()); + weIdAuth.setWeIdPrivateKey(weIdPrivateKey); + weIdAuth.setAuthenticationMethodId(cwdr.getUserWeIdPublicKey().getPublicKey() + "#keys-1"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuth); + + ResponseData createResp = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", createResp); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), createResp.getErrorCode().intValue()); + + // Verify this is OK + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), createResp.getResult()); + Assert.assertTrue(verify.getResult()); + + // Specify key ID to be "1" and it should be OK too + verify = credentialPojoService.verify(createCredentialPojoArgs.getIssuer(), + cwdr.getWeId() + "#keys-" + DataToolUtils.hash(pwKey.getPublicKey()).substring(58), createResp.getResult()); + Assert.assertTrue(verify.getResult()); + + // Specify key ID to be "0" and it should be semi-succeeded + verify = credentialPojoService.verify(createCredentialPojoArgs.getIssuer(), + "0", createResp.getResult()); + Assert.assertFalse(verify.getResult()); + Assert.assertEquals(verify.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_VERIFY_SUCCEEDED_WITH_WRONG_PUBLIC_KEY_ID.getCode()); + + } + + /** + * Test timestamp services. + */ + // NOTE: TODO when doing any local tests, please make sure this is enabled. + // This test is prohibited in CI workflow to reduce WeSign costs. + // @Test + public void testCreateAndVerifyTimestamp() { + // Happy path + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + List credPojoList = new ArrayList<>(); + credPojoList.add(response.getResult()); + WeIdAuthentication callerAuth = TestBaseUtil + .buildWeIdAuthentication(createWeIdResultWithSetAttr); + ResponseData resp = credentialPojoService + .createTrustedTimestamp(credPojoList, callerAuth); + CredentialPojo tscred = resp.getResult(); + Assert.assertNotNull(tscred); + System.out.println(DataToolUtils.serialize(tscred)); + ResponseData respData = credentialPojoService.verify(tscred.getIssuer(), tscred); + Assert.assertTrue(respData.getResult()); + + // Modify timestamp then.. + CredentialPojo modifiedTsCred = copyCredentialPojo(tscred); + Map claim = modifiedTsCred.getClaim(); + String tstamp = (String) claim.get("authoritySignature"); + claim.put("authoritySignature", tstamp + "a"); + modifiedTsCred.setClaim(claim); + respData = credentialPojoService.verify(modifiedTsCred.getIssuer(), modifiedTsCred); + Assert.assertFalse(respData.getResult()); + Assert.assertEquals(respData.getErrorCode().intValue(), + ErrorCode.TIMESTAMP_VERIFICATION_FAILED.getCode()); + modifiedTsCred = copyCredentialPojo(tscred); + claim = modifiedTsCred.getClaim(); + Long stamptime = (long) claim.get("timestamp"); + claim.put("timestamp", stamptime - 100); + modifiedTsCred.setClaim(claim); + respData = credentialPojoService.verify(modifiedTsCred.getIssuer(), modifiedTsCred); + Assert.assertFalse(respData.getResult()); + Assert.assertEquals(respData.getErrorCode().intValue(), + ErrorCode.TIMESTAMP_VERIFICATION_FAILED.getCode()); + + // SD credential should fail. + credPojoList = new ArrayList<>(); + credPojoList.add(credentialPojo); + credPojoList.add(selectiveCredentialPojo); + resp = credentialPojoService.createTrustedTimestamp(credPojoList, callerAuth); + Assert.assertNull(resp.getResult()); + Assert.assertEquals(resp.getErrorCode().intValue(), + ErrorCode.TIMESTAMP_CREATION_FAILED_FOR_SELECTIVELY_DISCLOSED.getCode()); + } + + /** + * case:when issuer and cpt publisher is same,createCredentialPojo success. + */ + @Test + public void testCreateMultiSignCredentialPojo_success() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + ResponseData credResp1 = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", credResp1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), credResp1.getErrorCode().intValue()); + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), credResp1.getResult()); + Assert.assertTrue(verify.getResult()); + + CreateWeIdDataResult weIdResult2 = createWeIdWithSetAttr(); + createCredentialPojoArgs = TestBaseUtil.buildCreateCredentialPojoArgs(weIdResult2); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialPojoArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialPojoArgs.setExpirationDate(expirationDate); + ResponseData credResp2 = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", credResp2); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), credResp2.getErrorCode().intValue()); + verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), credResp2.getResult()); + Assert.assertTrue(verify.getResult()); + + List credPojoList = new ArrayList<>(); + credPojoList.add(credResp1.getResult()); + credPojoList.add(credResp2.getResult()); + CreateWeIdDataResult weIdResult3 = createWeIdWithSetAttr(); + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(weIdResult3); + CredentialPojo doubleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + Assert.assertEquals(doubleSigned.getCptId(), + CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT); + Assert.assertEquals(doubleSigned.getExpirationDate(), expirationDate); + ResponseData verifyResp = credentialPojoService + .verify(doubleSigned.getIssuer(), doubleSigned); + Assert.assertTrue(verifyResp.getResult()); + credPojoList = new ArrayList<>(); + credPojoList.add(doubleSigned); + CredentialPojo tripleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + verifyResp = credentialPojoService.verify(doubleSigned.getIssuer(), tripleSigned); + Assert.assertTrue(verifyResp.getResult()); + } + + /** + * case:when issuer and cpt publisher is same,createCredentialPojo success. + */ + @Test + public void testCreateMultiSignCredentialPojo_failure() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + ResponseData credResp1 = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", credResp1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), credResp1.getErrorCode().intValue()); + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), credResp1.getResult()); + Assert.assertTrue(verify.getResult()); + + CreateWeIdDataResult weIdResult2 = createWeIdWithSetAttr(); + createCredentialPojoArgs = TestBaseUtil.buildCreateCredentialPojoArgs(weIdResult2); + createCredentialPojoArgs.setCptId(10); + Long expirationDate = DateUtils.convertToNoMillisecondTimeStamp( + createCredentialPojoArgs.getExpirationDate() + 24 * 60 * 60); + createCredentialPojoArgs.setExpirationDate(expirationDate); + ResponseData credResp2 = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", credResp2); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), credResp2.getErrorCode().intValue()); + verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), credResp2.getResult()); + Assert.assertFalse(verify.getResult()); + + List credPojoList = new ArrayList<>(); + credPojoList.add(credResp1.getResult()); + credPojoList.add(credResp2.getResult()); + CreateWeIdDataResult weIdResult3 = createWeIdWithSetAttr(); + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(weIdResult3); + CredentialPojo doubleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + Assert.assertEquals(doubleSigned.getCptId(), + CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT); + Assert.assertEquals(doubleSigned.getExpirationDate(), expirationDate); + ResponseData verifyResp = credentialPojoService + .verify(doubleSigned.getIssuer(), doubleSigned); + Assert.assertFalse(verifyResp.getResult()); + credPojoList = new ArrayList<>(); + credPojoList.add(doubleSigned); + CredentialPojo tripleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + verifyResp = credentialPojoService.verify(tripleSigned.getIssuer(), tripleSigned); + Assert.assertFalse(verifyResp.getResult()); + } + + @Test + public void testLiteCredentialPojo() { + CreateWeIdDataResult createWeIdDataResult = super.createWeId(); + CreateCredentialPojoArgs> args = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdDataResult); + args.setType(CredentialType.LITE1); + args.setCptId(cptBaseInfo.getCptId()); + ResponseData response = credentialPojoService.createCredential(args); + LogUtil.info(logger, "createLiteCredential", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + CredentialPojo liteCredential = response.getResult(); + ResponseData resp = + credentialPojoService.verify(liteCredential.getIssuer(), liteCredential); + Assert.assertTrue(resp.getResult()); + + // LiteCredential: + // 1. getThumbprint() -> signature (针对凭证claim内容生成thumbprint,用私钥生成签名) + String thumbprint = CredentialPojoUtils + .getLiteCredentialThumbprintWithoutSig(liteCredential); + System.out.println("Lite Credential Thumbprint: " + thumbprint + ", Thumbprint hash: " + + new CryptoSuite(0).hash(thumbprint) + ", signature: " + liteCredential.getSignature()); + // 2. getHash() -> createEvidence (对凭证完整内容包括签名内容进行hash,claim支持选择性披露) + System.out.println("Lite Credential Hash: " + + CredentialPojoUtils.getLiteCredentialPojoHash(liteCredential)); + Assert.assertEquals(CredentialPojoUtils.getLiteCredentialPojoHash(liteCredential), + liteCredential.getHash()); + // 3. toJson() -> encrypt (唯一的序列化方法,瘦身,用于打包传输) + System.out.println("Lite Credential toJson: " + liteCredential.toJson()); + + // Original CredentialPojo: + CredentialPojo tempCredential = copyCredentialPojo(credentialPojo); + thumbprint = CredentialPojoUtils.getCredentialThumbprintWithoutSig(tempCredential, + tempCredential.getSalt(), null); + System.out.println("Original Credential Thumbprint: " + thumbprint); + System.out.println("Original Credential Hash: " + + CredentialPojoUtils.getCredentialPojoHash(tempCredential, null)); + System.out.println("Original Credential toJson: " + tempCredential.toJson()); + + // Original SD CredentialPojo: + CredentialPojo tempSdCredential = copyCredentialPojo(selectiveCredentialPojo); + thumbprint = CredentialPojoUtils.getCredentialThumbprintWithoutSig(tempSdCredential, + tempSdCredential.getSalt(), null); + System.out.println("Original SD Credential Thumbprint: " + thumbprint); + System.out.println("Original SD Credential Hash: " + + CredentialPojoUtils.getCredentialPojoHash(tempSdCredential, null)); + System.out.println("Original SD Credential toJson: " + tempSdCredential.toJson()); + } + + /** + * case:when issuer is register authentication issuer, cpt publisher is not auth issuer, + * createCredentialPojo success. + */ + @Test + public void testCreateCredentialPojo_authenticationIssuerSuccess() { + + CreateWeIdDataResult createWeIdDataResult = super.createWeId(); + super.registerAuthorityIssuer(createWeIdDataResult); + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdDataResult); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertTrue(verify.getResult()); + } + + /** + * case:cpt publisher is auth issuer, createCredentialPojo success. + */ + @Test + public void testCreateCredentialPojo_authenticationCptSuccess() { + + CreateWeIdDataResult createWeIdDataResult = super.createWeId(); + super.registerAuthorityIssuer(createWeIdDataResult); + authorityIssuerService.recognizeAuthorityIssuer(createWeIdDataResult.getWeId(), + new WeIdPrivateKey(privateKey)); + CptBaseInfo cptBaseInfo = super.registerCpt(createWeIdDataResult); + Assert.assertTrue(cptBaseInfo.getCptId() < 2000000); + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertTrue(verify.getResult()); + } + + /** + * case:repeat createCredentialPojo success. + */ + @Test + public void testCreateCredentialPojo_repeatSuccess() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + ResponseData response1 = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response1); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); + } + + /** + * case:createCredential success refer to doc. + */ + @Test + public void testCreateCredentialPojo_sampleFail() { + + HashMap claim = new HashMap<>(); + claim.put("student", new CptBaseInfo()); + claim.put("name", "李白"); + claim.put("age", 1300); + claim.put("poiet", "桃花潭水深千尺,不及汪伦送我情"); + CreateCredentialPojoArgs createCredentialArgs = new CreateCredentialPojoArgs(); + createCredentialArgs.setClaim(claim); + + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialArgs.setExpirationDate(System.currentTimeMillis() + 6000); + createCredentialArgs.setIssuer(createWeIdResultWithSetAttr.getWeId()); + + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResultWithSetAttr.getWeId()); + weIdAuthentication.setAuthenticationMethodId( + createWeIdResultWithSetAttr.getUserWeIdPublicKey().getPublicKey()); + weIdAuthentication.setWeIdPrivateKey( + createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + createCredentialArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = + credentialPojoService.createCredential(createCredentialArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialArgs.getIssuer(), response.getResult()); + LogUtil.info(logger, "verify", verify); + Assert.assertEquals( + ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + /** + * case:when weIdAuthentication is null,createCredentialPojo return ILLEGAL_INPUT. + */ + @Test + public void testCreateCredentialPojo_weIdAuthenticationNull() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setWeIdAuthentication(new WeIdAuthentication()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: createCredentialPojoArgs is null,return ILLEGAL_INPUT. + */ + @Test + public void testCreateCredentialPojo_credentialArgsNull() { + + ResponseData response = + credentialPojoService.createCredential(null); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:cptId is null,return ILLEGAL_INPUT . + */ + @Test + public void testCreateCredential_cptIdNull() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: cptId is minus number,return CREDENTIAL_CPT_NOT_EXISTS. + */ + @Test + public void testCreateCredential_cptIdMinus() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(-1); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CPT_ID_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + } + + /** + * case: cptId is not exists,createCredentialPojo success but verify fail. + */ + @Test + public void testCreateCredential_cptIdNotExist() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(999999999); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), response.getResult()); + LogUtil.info(logger, "verify createCredentialPojo", verify); + Assert.assertEquals(ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), + verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + /** + * case: cptId is belongs to others weIdentity dId. + */ + @Test + public void testCreateCredential_otherCptIdSuccess() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + CptBaseInfo cptBaseInfoNew = super.registerCpt(createWeIdNew); + createCredentialPojoArgs.setCptId(cptBaseInfoNew.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService.verify( + createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertTrue(verify.getResult()); + } + + /** + * case: issuer is null. + */ + @Test + public void testCreateCredential_issuerNull() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuer(null); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: issuer is invalid. + */ + @Test + public void testCreateCredential_invalidIssuer() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuer("di:weid:0x11!@#$%^&*()_+zhon 中国》《?12qwe"); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: private key is sdk private key. + */ + @Test + public void testCreateCredential_sdkPriKey() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + WeIdAuthentication weIdAuthentication = createCredentialPojoArgs.getWeIdAuthentication(); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + weIdAuthentication.setWeIdPrivateKey(weIdPrivateKey); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + + /** + * case: issuance date = 0,create success and verify success. + */ + @Test + public void createCredential_withIssuanceZero() { + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuanceDate(0L); + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:issuance date data is minus number. + */ + @Test + public void testCreateCredential_issuanceDateMinus() { + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuanceDate(-1L); + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + } + + /** + * case: issuance date is a big integer. + */ + @Test + public void testCreateCredential_bigIssuanceDate() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuanceDate(Long.MAX_VALUE); + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + } + + /** + * case:issuance date is Long.MIN_VALUE + */ + @Test + public void testCreateCredential_minIsuanceDate() { + + CreateCredentialPojoArgs> createCredentialPojoArgs + = TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setIssuanceDate(Long.MIN_VALUE); + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: expirationDate <= 0. + */ + @Test + public void testCreateCredential_minusExpirationDate() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setExpirationDate(0L); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: expirationDate <= now. + */ + @Test + public void testCreateCredential_passedExpirationDate() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setExpirationDate(System.currentTimeMillis() - 1000000); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:expiration date is null. + */ + @Test + public void testCreateCredential_expirationDateNull() { + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setExpirationDate(null); + + ResponseData response = credentialPojoService + .createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: claim is null. + */ + @Test + public void testCreateCredential_claimNull() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + createCredentialPojoArgs.setClaim(null); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: claim is xxxxxxx. + */ + @Test + public void testCreateCredential_invalidClaim() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + HashMap claim = new HashMap<>(); + claim.put("xxxxxxxxxxxxxx", "xxxxxxxxxxxxxx"); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertEquals( + ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + /** + * case:claim is a json. + */ + @Test + public void testCreateCredential_jsonClaim() { + + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + Map claim = new HashMap<>(); + claim.put("name", 20); + createCredentialPojoArgs.setClaim(claim); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertEquals( + ErrorCode.CREDENTIAL_CLAIM_DATA_ILLEGAL.getCode(), verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + /** + * case: weIdPrivateKey is null. + */ + @Test + public void testCreateCredential_priKeyNull() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResultWithSetAttr.getWeId()); + weIdAuthentication.setAuthenticationMethodId( + createWeIdResultWithSetAttr.getUserWeIdPublicKey().getPublicKey()); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: publicKey is null. + */ + @Test + public void testCreateCredential_pubKeyNull() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResultWithSetAttr.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + weIdAuthentication.setAuthenticationMethodId( + createWeIdResultWithSetAttr.getUserWeIdPublicKey().getPublicKey() + "56"); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(createCredentialPojoArgs.getIssuer(), response.getResult()); + Assert.assertTrue(verify.getResult()); + + } + + /** + * case: issuer and weIdAuthentication.weId is different,createCredentialPojo fail. + */ + @Test + public void testCreateCredential_otherWeId() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdNew.getWeId()); + weIdAuthentication.setAuthenticationMethodId(createWeIdNew.getUserWeIdPublicKey().getPublicKey()); + weIdAuthentication.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + } + + /** + * case: privateKey is issuer private key. + */ + @Test + public void testCreateCredential_issuerPriKey() { + + CreateCredentialPojoArgs createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdNew.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + createCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); + + ResponseData response = + credentialPojoService.createCredential(createCredentialPojoArgs); + LogUtil.info(logger, "createCredentialPojo", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + } + + @Test + public void testCreateAuthTokenAll() throws Exception { + + // Enforce a Register/Update system CPT first + WeIdAuthentication sdkAuthen = new WeIdAuthentication(); + //ECKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate(new BigInteger(privateKey)); + //CryptoKeyPair keyPair = DataToolUtils.cryptoSuite.getKeyPairFactory().createKeyPair(new BigInteger(privateKey)); + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey)); + String keyWeId = WeIdUtils.convertAddressToWeId(DataToolUtils.addressFromPublic(new BigInteger(publicKey, 10))); + sdkAuthen.setWeId(keyWeId); + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey(privateKey); + sdkAuthen.setWeIdPrivateKey(weIdPrivateKey); + if (!weIdService.isWeIdExist(keyWeId).getResult()) { + CreateWeIdArgs wargs = new CreateWeIdArgs(); + wargs.setWeIdPrivateKey(weIdPrivateKey); + //wargs.setPublicKey(keyPair.getPublicKey().toString(10)); + /*BigInteger publicKey = + new BigInteger(1, Numeric.hexStringToByteArray(keyPair.getHexPublicKey()));*/ + wargs.setPublicKey(publicKey); + weIdService.createWeId(wargs); + } +// String cptJsonSchema = DataToolUtils.generateDefaultCptJsonSchema(Class.forName("com.webank.weid.protocol.cpt.Cpt101")); + String cptJsonSchema = DataToolUtils.generateDefaultCptJsonSchema(101); + CptStringArgs args = new CptStringArgs(); + args.setCptJsonSchema(cptJsonSchema); + args.setWeIdAuthentication(sdkAuthen); + if (cptService.queryCpt(CredentialConstant.AUTHORIZATION_CPT).getResult() == null) { + cptService.registerCpt(args, CredentialConstant.AUTHORIZATION_CPT); + } else { + cptService.updateCpt(args, CredentialConstant.AUTHORIZATION_CPT); + } + + // Init params + Cpt101 authInfo = new Cpt101(); + authInfo.setFromWeId(createWeIdResultWithSetAttr.getWeId()); + String toWeId = this.createWeIdWithSetAttr().getWeId(); + authInfo.setToWeId(toWeId); + authInfo.setDuration(360000L); + authInfo.setResourceId(UUID.randomUUID().toString()); + authInfo.setServiceUrl("http://127.0.0.1:6011/fetch-data"); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResultWithSetAttr.getWeId()); + weIdAuthentication.setWeIdPrivateKey(createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + weIdAuthentication.setAuthenticationMethodId(createWeIdResultWithSetAttr.getWeId() + "#keys-0"); + + // Create and check + ResponseData authTokenCredResp = credentialPojoService + .createDataAuthToken(authInfo, weIdAuthentication); + Assert.assertEquals(authTokenCredResp.getErrorCode().intValue(), + ErrorCode.SUCCESS.getCode()); + CredentialPojo authToken = authTokenCredResp.getResult(); + ResponseData verifyResp = credentialPojoService + .verify(authToken.getIssuer(), authToken); + Assert.assertTrue(verifyResp.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestCreatePresentation.java b/src/test/java/com/webank/weid/full/credentialpojo/TestCreatePresentation.java new file mode 100644 index 00000000..d373dfab --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestCreatePresentation.java @@ -0,0 +1,646 @@ + + +package com.webank.weid.full.credentialpojo; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.Challenge; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.PresentationE; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; + +public class TestCreatePresentation extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestCreatePresentation.class); + + private static CredentialPojo credentialPojo = null; + + private static CredentialPojo credentialPojoNew = null; + + private static List credentialList = new ArrayList<>(); + + private static PresentationPolicyE presentationPolicyE = + PresentationPolicyE.create("policy.json"); + + private static Challenge challenge = null; + + + @Override + public synchronized void testInit() { + super.testInit(); + + if (credentialPojo == null) { + credentialPojo = super.createCredentialPojo(createCredentialPojoArgs); + } + if (credentialPojoNew == null) { + credentialPojoNew = super.createCredentialPojo(createCredentialPojoArgsNew); + } + if (presentationPolicyE != null) { + presentationPolicyE = PresentationPolicyE.create("policy.json"); + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy = policyMap.get(1000); + policyMap.remove(1000); + policyMap.put(createCredentialPojoArgs.getCptId(), cliamPolicy); + } + if (challenge == null) { + challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis())); + } + + if (credentialList == null || credentialList.size() == 0) { + credentialList.add(credentialPojo); + } + + } + + /** + * case:create Presentation success. + */ + @Test + public void testCreatePresentation_success() { + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: credential list have two credentialPojo. + */ + @Test + public void testCreatePresentation_credentialListsSuccess() { + + credentialList.add(credentialPojoNew); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + credentialList.remove(credentialPojoNew); + } + + /** + * case: credential list have two credentialPojo. + */ + @Test + public void testCreatePresentation_credentialListRepeatSuccess() { + + CredentialPojo credentialPojoCopy = copyCredentialPojo(credentialPojo); + credentialList.add(credentialPojoCopy); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + credentialList.remove(credentialPojoCopy); + } + + /** + * case: credentiallist.size==0 . + */ + @Test + public void testCreatePresentation_credentialListEmpty() { + + credentialList.clear(); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case: credentiallist is null. + */ + @Test + public void testCreatePresentation_credentialListNull() { + + credentialList.clear(); + + ResponseData response = credentialPojoService.createPresentation( + null, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:presentationPolicyE is null. + */ + @Test + public void testCreatePresentation_presentationPolicyENull() { + + ResponseData response + = credentialPojoService.createPresentation( + credentialList, + null, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.PRESENTATION_POLICY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:presentationPolicyE policy is blank. + */ + @Test + public void testCreatePresentation_policyNull() { + + credentialList.clear(); + credentialList.add(credentialPojoNew); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + ClaimPolicy claimPolicy + = presentationPolicyE.getPolicy().get(copyCredentialPojo.getCptId()); + claimPolicy.setFieldsToBeDisclosed(""); + credentialList.add(copyCredentialPojo); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + credentialList.remove(credentialPojoNew); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + + } + + /** + * case:presentationPolicyE policy is different with credentialPojo.claim + */ + + @Test + public void testCreatePresentation_policyDifferentWithClaim() { + + credentialList.clear(); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + ClaimPolicy claimPolicy + = presentationPolicyE.getPolicy().get(copyCredentialPojo.getCptId()); + claimPolicy.setFieldsToBeDisclosed( + "{\"name\":1,\"gender\":0,\"age\":1,\"id\":1,\"yy\":1}"); + credentialList.add(copyCredentialPojo); + credentialList.add(credentialPojoNew); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + credentialList.remove(credentialPojoNew); + + Assert.assertEquals(ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + } + + /** + * case:presentationPolicyE policy is different with credentialPojo.claim + */ + + @Test + public void testCreatePresentation_policyDisclosedId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map claimMap = copyCredentialPojo.getClaim(); + String weId = (String) claimMap.get("id"); + claimMap.replace("id", weId, + "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6123456"); + ClaimPolicy claimPolicy + = presentationPolicyE.getPolicy().get(copyCredentialPojo.getCptId()); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + credentialList.clear(); + credentialList.add(copyCredentialPojo); + credentialList.add(credentialPojoNew); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + credentialList.remove(credentialPojoNew); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + + } + + /** + * case:presentationPolicyE policy is different with credentialPojo.claim + */ + + @Test + public void testCreatePresentation_policyClosedId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map claimMap = copyCredentialPojo.getClaim(); + String weId = (String) claimMap.get("id"); + claimMap.replace("id", weId, + "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6123456"); + + ClaimPolicy claimPolicy + = presentationPolicyE.getPolicy().get(copyCredentialPojo.getCptId()); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":0}"); + credentialList.clear(); + credentialList.add(copyCredentialPojo); + credentialList.add(credentialPojoNew); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + credentialList.remove(credentialPojoNew); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:presentationPolicyE policy is different with credentialPojo.claim. + */ + + @Test + public void testCreatePresentation_credetialListHasDupilcate() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map claimMap = copyCredentialPojo.getClaim(); + String weId = (String) claimMap.get("id"); + claimMap.replace("id", weId, + "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6123456"); + + ClaimPolicy claimPolicy + = presentationPolicyE.getPolicy().get(copyCredentialPojo.getCptId()); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":0}"); + credentialList.clear(); + credentialList.add(copyCredentialPojo); + credentialList.add(credentialPojo); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + credentialList.remove(credentialPojo); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:credentialPojo.cptid is different with presentationPolicyE.cptId. + */ + @Test + public void testCreatePresentation_OtherCptId() { + + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy = policyMap.get(credentialPojo.getCptId()); + policyMap.remove(credentialPojo.getCptId()); + policyMap.put(credentialPojoNew.getCptId(), cliamPolicy); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.PRESENTATION_CREDENTIALLIST_MISMATCH_CLAIM_POLICY.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + policyMap.remove(credentialPojoNew.getCptId()); + policyMap.put(credentialPojo.getCptId(), cliamPolicy); + } + + /** + * case:credentialPojo.issuer is different with PresentationPolicyE.policyPublisherWeId. + */ + @Test + public void testCreatePresentation_issuerAndPolicyPublisherDifferent() { + + final String policyPublisherWeId = presentationPolicyE.getPolicyPublisherWeId(); + presentationPolicyE.setPolicyPublisherWeId(credentialPojoNew.getIssuer()); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + presentationPolicyE.setPolicyPublisherWeId(policyPublisherWeId); + } + + /** + * case:credentialPojo.issuer is different with PresentationPolicyE.policyPublisherWeId. + */ + @Test + public void testCreatePresentation_issuerNotExist() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), + DateUtils.getNoMillisecondTimeStampString()); + copyCredentialPojo.setIssuer(weId); + credentialList.clear(); + credentialList.add(copyCredentialPojo); + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:credentialPojo.issuer is different with PresentationPolicyE.policyPublisherWeId. + */ + @Test + public void testCreatePresentation_issuerNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuer(null); + credentialList.clear(); + credentialList.add(copyCredentialPojo); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:PresentationPolicyE.policyPublisherWeId is not exist. + */ + @Test + public void testCreatePresentation_publisherIssuerNotExist() { + + final String policyPublisherWeId = presentationPolicyE.getPolicyPublisherWeId(); + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), "ffff"); + presentationPolicyE.setPolicyPublisherWeId(weId); + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + presentationPolicyE.setPolicyPublisherWeId(policyPublisherWeId); + + Assert.assertEquals(ErrorCode.PRESENTATION_POLICY_PUBLISHER_WEID_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + } + + /** + * case:PresentationPolicyE.policyPublisherWeId is null. + */ + @Test + public void testCreatePresentation_publisherIssuerNull() { + + final String policyPublisherWeId = presentationPolicyE.getPolicyPublisherWeId(); + presentationPolicyE.setPolicyPublisherWeId(null); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.PRESENTATION_POLICY_PUBLISHER_WEID_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + presentationPolicyE.setPolicyPublisherWeId(policyPublisherWeId); + } + + /** + * case:challenge.weid is not exist. + */ + @Test + public void testCreatePresentation_challengeWeIdNotExist() { + + final String challengeWeId = challenge.getWeId(); + challenge.setWeId("did:weid:101:0x39e5e6f663ef77409144014ceb063713b6123456"); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.PRESENTATION_CHALLENGE_WEID_MISMATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + challenge.setWeId(challengeWeId); + } + + /** + * case:issuer and challenge.weid are different. + */ + @Test + public void testCreatePresentation_challengeWeIdDifferentIssuer() { + + final String challengeWeId = challenge.getWeId(); + challenge.setWeId(credentialPojoNew.getIssuer()); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.PRESENTATION_CHALLENGE_WEID_MISMATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + challenge.setWeId(challengeWeId); + } + + /** + * case:challenge.weid is null. + */ + @Test + public void testCreatePresentation_challengeWeIdNull() { + + final String challengeWeId = challenge.getWeId(); + challenge.setWeId(null); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + challenge.setWeId(challengeWeId); + } + + /** + * case:challenge.weid is null. + */ + @Test + public void testCreatePresentation_WeIdAuthenticationPrivateKeyNotMatch() { + + WeIdAuthentication weIdAuthentication = TestBaseUtil + .buildWeIdAuthentication(createWeIdResultWithSetAttr); + weIdAuthentication.setWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + weIdAuthentication + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:credentialPojo.claim put("claim",claim) should success. + */ + @Test + public void testCreatePresentation_ClaimInClaim() { + + credentialList.clear(); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map originalClaim = copyCredentialPojo.getClaim(); + if (originalClaim != null) { + Map claim = DataToolUtils + .deserialize(DataToolUtils.serialize(originalClaim), HashMap.class); + originalClaim.put("claim", claim); + } + credentialList.add(copyCredentialPojo); + + ClaimPolicy claimPolicy = presentationPolicyE + .getPolicy().get(copyCredentialPojo.getCptId()); + final String policy = claimPolicy.getFieldsToBeDisclosed(); + claimPolicy + .setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1,\"claim\":1}"); + + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + LogUtil.info(logger, "TestCreatePresentation", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + claimPolicy.setFieldsToBeDisclosed(policy); + } + + +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestCreateSelectiveCredential.java b/src/test/java/com/webank/weid/full/credentialpojo/TestCreateSelectiveCredential.java new file mode 100644 index 00000000..7c72e547 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestCreateSelectiveCredential.java @@ -0,0 +1,864 @@ + + +package com.webank.weid.full.credentialpojo; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.request.CreateCredentialPojoArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.CredentialPojoUtils; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; + +/** + * createCredential method for testing CredentialService. + * + * @author v_wbgyang + */ +public class TestCreateSelectiveCredential extends TestBaseService { + + private static final Logger logger = LoggerFactory + .getLogger(TestCreateSelectiveCredential.class); + + @Override + public synchronized void testInit() { + + super.testInit(); + if (credentialPojo == null) { + credentialPojo = super.createCredentialPojo(createCredentialPojoArgs); + } + } + + /** + * case:createSelectiveCredential success. + */ + @Test + public void testCreateSelectiveCredential_success() { + Assert.assertNotNull(selectiveCredentialPojo); + + ResponseData verify = credentialPojoService + .verify(selectiveCredentialPojo.getIssuer(), selectiveCredentialPojo); + LogUtil.info(logger, "selectiveCredentialPojo", selectiveCredentialPojo); + LogUtil.info(logger, "verifyCredentialPojo", verify); + Assert.assertTrue(verify.getResult()); + } + + @Test + public void testTwoCredentialPojoEqual() { + CredentialPojo tmpCred = copyCredentialPojo(selectiveCredentialPojo); + Assert.assertTrue(CredentialPojoUtils.isEqual(selectiveCredentialPojo, tmpCred)); + } + + @Test + public void testCreateFullyNonSdCredential() { + CreateCredentialPojoArgs> createCredentialPojoArgs = + TestBaseUtil.buildCreateCredentialPojoArgs(createWeIdResultWithSetAttr); + createCredentialPojoArgs.setCptId(cptBaseInfo.getCptId()); + CredentialPojo credential = + credentialPojoService.createCredential(createCredentialPojoArgs).getResult(); + Assert.assertFalse(CredentialPojoUtils.isSelectivelyDisclosed(credential.getSalt())); + logger.info(DataToolUtils.serialize(credential)); + CredentialPojo nonSdCredential = + credentialPojoService.createSelectiveCredential(credential, + CredentialPojoUtils.generateNonDisclosedPolicy(credential)).getResult(); + Assert.assertNotNull(nonSdCredential); + Assert.assertTrue(CredentialPojoUtils.isSelectivelyDisclosed(nonSdCredential.getSalt())); + logger.info(DataToolUtils.serialize(nonSdCredential)); + Assert.assertTrue(CredentialPojoUtils + .getCredentialThumbprintWithoutSig(credential, credential.getSalt(), null) + .equalsIgnoreCase(CredentialPojoUtils + .getCredentialThumbprintWithoutSig(nonSdCredential, nonSdCredential.getSalt(), + null))); + } + + /** + * case:when issuer and cpt publisher is same,createCredentialPojo success. + */ + @Test + public void testCreateMultiSignSdCredentialPojo_success() { + List credPojoList = new ArrayList<>(); + credPojoList.add(selectiveCredentialPojo); + CreateWeIdDataResult weIdResult = createWeIdWithSetAttr(); + WeIdAuthentication callerAuth = TestBaseUtil.buildWeIdAuthentication(weIdResult); + CredentialPojo doubleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + Assert.assertEquals(doubleSigned.getCptId(), + CredentialConstant.CREDENTIALPOJO_EMBEDDED_SIGNATURE_CPT); + + ResponseData verifyResp = credentialPojoService + .verify(doubleSigned.getIssuer(), doubleSigned); + Assert.assertTrue(verifyResp.getResult()); + credPojoList = new ArrayList<>(); + credPojoList.add(doubleSigned); + CredentialPojo tripleSigned = credentialPojoService.addSignature(credPojoList, callerAuth) + .getResult(); + verifyResp = credentialPojoService.verify(doubleSigned.getIssuer(), tripleSigned); + Assert.assertTrue(verifyResp.getResult()); + } + + @Test + public void testMultiSignPojo_fromToJson_ReplaceInnerCredential() throws Exception { + List credPojoList = new ArrayList<>(); + credPojoList.add(selectiveCredentialPojo); + credPojoList.add(credentialPojo); + WeIdAuthentication callerAuth = TestBaseUtil + .buildWeIdAuthentication(createWeIdResultWithSetAttr); + CredentialPojo doubleSigned = + credentialPojoService.addSignature(credPojoList, callerAuth).getResult(); + System.out.println("A part: " + CredentialPojoUtils + .getEmbeddedCredentialThumbprintWithoutSig(credPojoList)); + String serializedjson = doubleSigned.toJson(); + System.out.println("A is: " + serializedjson); + CredentialPojo cpj = CredentialPojo.fromJson(serializedjson); + Assert.assertTrue(CredentialPojoUtils.isEqual(cpj, doubleSigned)); + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + CredentialPojo tempPojo = response.getResult(); + credPojoList = new ArrayList<>(); + credPojoList.add(selectiveCredentialPojo); + credPojoList.add(tempPojo); + System.out.println("B part: " + CredentialPojoUtils + .getEmbeddedCredentialThumbprintWithoutSig(credPojoList)); + CredentialPojo modifiedDoubleSigned = copyCredentialPojo(doubleSigned); + Map modifiedClaim = new HashMap<>(); + modifiedClaim.put("credentialList", credPojoList); + modifiedDoubleSigned.setClaim(modifiedClaim); + serializedjson = modifiedDoubleSigned.toJson(); + System.out.println("B is: " + serializedjson); + Assert.assertTrue( + credentialPojoService.verify(modifiedDoubleSigned.getIssuer(), modifiedDoubleSigned) + .getResult()); + } + + @Test + public void testMultiSignPojo_sedeserialize() throws Exception { + List credPojoList = new ArrayList<>(); + credPojoList.add(selectiveCredentialPojo); + credPojoList.add(credentialPojo); + WeIdAuthentication callerAuth = TestBaseUtil + .buildWeIdAuthentication(createWeIdResultWithSetAttr); + CredentialPojo doubleSigned = + credentialPojoService.addSignature(credPojoList, callerAuth).getResult(); + System.out.println(doubleSigned); + String serializedjson = DataToolUtils.serialize(doubleSigned); + System.out.println(serializedjson); + CredentialPojo testcpj = DataToolUtils.deserialize(serializedjson, CredentialPojo.class); + System.out.println(testcpj); + Assert.assertTrue(CredentialPojoUtils.isEqual(doubleSigned, testcpj)); + } + + /** + * case:createSelectiveCredential fail. + */ + @Test + public void testCreateSelectiveCredential_verifyClaimId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map claimMap = copyCredentialPojo.getClaim(); + claimMap.remove("id"); + claimMap.put("id", "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6112121"); + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(copyCredentialPojo.getIssuer(), copyCredentialPojo); + Assert.assertFalse(verify.getResult()); + } + + /** + * case:createSelectiveCredential success. + */ + @Test + public void testCreateSelectiveCredential_notVerifyClaimId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map claimMap = copyCredentialPojo.getClaim(); + claimMap.remove("id"); + claimMap.put("id", "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6112121"); + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":0}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case: createSelectiveCredential repeat success. + */ + @Test + public void testCreateSelectiveCredential_repeatSucess() { + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + Map claimMap = credentialPojo.getClaim(); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotEquals( + claimMap.get("gender"), response.getResult().getClaim().get("gender")); + + ResponseData response1 = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotEquals( + claimMap.get("gender"), response1.getResult().getClaim().get("gender")); + } + + /** + * case:context contain any string. + */ + @Test + public void testCreateSelectiveCredential_contextContainsAnyStr() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + copyCredentialPojo.setContext("~!@#$%^&*()_中国123we"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + + } + + /** + * case:context is null. + */ + @Test + public void testCreateSelectiveCredential_contextNull() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setContext(null); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:context is blank. + */ + @Test + public void testCreateSelectiveCredential_contextBlank() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setContext(""); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:context is too long . + */ + @Test + public void testCreateSelectiveCredential_contextTooLong() { + + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (i % 127); + } + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setContext(String.valueOf(chars)); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:type contain any string. + */ + @Test + public void testCreateSelectiveCredential_typeContainsAnyStr() { + + List stringList = new ArrayList<>(); + stringList.add("你好哈"); + stringList.add("!@#$%^&*(*)/.,><;lkjhg"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setType(stringList); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:type is null. + */ + @Test + public void testCreateSelectiveCredential_typeNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setType(null); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_TYPE_IS_NULL.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + + + } + + /** + * case:type is blank. + */ + @Test + public void testCreateSelectiveCredential_typeBlank() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setType(new ArrayList<>()); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_TYPE_IS_NULL.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:type is too long. + */ + @Test + public void testCreateSelectiveCredential_typeTooLong() { + List stringList = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + String s = "ah" + Math.random(); + stringList.add(s); + } + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setType(stringList); + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:cptid not exist. + */ + @Test + public void testCreateSelectiveCredential_cptIdNotExist() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setCptId(Integer.MAX_VALUE); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(copyCredentialPojo.getIssuer(), copyCredentialPojo); + Assert.assertEquals( + ErrorCode.CREDENTIAL_CPT_NOT_EXISTS.getCode(), verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + /** + * case:credentialPojo.issuer is no exist. + */ + @Test + public void testCreateSelectiveCredential_issuerNotExist() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), "ffff"); + copyCredentialPojo.setIssuer(weId); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + ResponseData verify = credentialPojoService + .verify(copyCredentialPojo.getIssuer(), response.getResult()); + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + verify.getErrorCode().intValue()); + Assert.assertFalse(verify.getResult()); + } + + + /** + * case:credentialPojo.issuer is a invalid issuer. + */ + @Test + public void testCreateSelectiveCredential_invalidIssuer() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), + DateUtils.getNoMillisecondTimeStampString()); + copyCredentialPojo.setIssuer(weId); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:issuer is null. + */ + @Test + public void testCreateSelectiveCredential_issuerNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuer(null); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:issuer is blank. + */ + @Test + public void testCreateSelectiveCredential_issuerBlank() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuer(""); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:expirationDatePassed. + */ + @Test + public void testCreateSelectiveCredential_expirationDatePassed() { + + long currentDate = System.currentTimeMillis(); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(currentDate - 1000); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:IssuanceDate has been passed. + */ + @Test + public void testCreateSelectiveCredential_IssuanceDatePassed() { + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + long currentDate = System.currentTimeMillis(); + copyCredentialPojo.setIssuanceDate(currentDate - 10000); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:IssuanceDate bigger than expirationDate. + */ + @Test + public void testCreateSelectiveCredential_expirationed() { + long currentDate = System.currentTimeMillis(); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(currentDate + 20000); + copyCredentialPojo.setExpirationDate(currentDate + 10000); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim is null. + */ + @Test + public void testCreateSelectiveCredential_claimNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setClaim(null); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim is blank. + */ + @Test + public void testCreateSelectiveCredential_claimBlank() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setClaim(new HashMap<>()); + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim policy contain key that claim not have. + */ + @Test + public void testCreateSelectiveCredential_claimPolicyMore() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed( + "{\"name\":1,\"gender\":0,\"age\":1,\"id\":1,\"birthday\":1986}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim contain keys but claim policy not. + */ + @Test + public void testCreateSelectiveCredential_claimPolicyLess() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:bad claim policy . + */ + @Test + public void testCreateSelectiveCredential_badClaimPolicy() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_DISCLOSURE_DATA_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim policy key contains twice . + */ + @Test + public void testCreateSelectiveCredential_claimPolicyRepeat() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:claim policy value is null. + */ + @Test + public void testCreateSelectiveCredential_claimPolicyContainsNull() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":0,\"age\":1,\"id\":null}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_POLICY_DISCLOSUREVALUE_ILLEGAL.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case:claim policy all open . + */ + @Test + public void testCreateSelectiveCredential_claimPolicyAllOpen() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":1,\"gender\":1,\"age\":1,\"id\":1}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:claim policy all close . + */ + @Test + public void testCreateSelectiveCredential_claimPolicyAllClose() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + + ResponseData response = + credentialPojoService.createSelectiveCredential(credentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + } + + /** + * case:proof is null. + */ + @Test + public void testCreateSelectiveCredential_proofNull() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setProof(null); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:proof is blank. + */ + @Test + public void testCreateSelectiveCredential_proofBlank() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setProof(new HashMap<>()); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:proof is blank. + */ + @Test + public void testCreateSelectiveCredential_proofRemoveCreatorSucess() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map proofMap = copyCredentialPojo.getProof(); + proofMap.remove("creator"); + copyCredentialPojo.setProof(proofMap); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + + /** + * case:proof is blank. + */ + @Test + public void testCreateSelectiveCredential_proofRemoveSalt() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map proofMap = copyCredentialPojo.getProof(); + proofMap.remove("salt"); + copyCredentialPojo.setProof(proofMap); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_POLICY_FORMAT_DOSE_NOT_MATCH_CLAIM.getCode(), + response.getErrorCode().intValue() + ); + Assert.assertNull(response.getResult()); + } + + /** + * case:proof is blank. + */ + @Test + public void testCreateSelectiveCredential_proofRemoveSignature() { + + ClaimPolicy claimPolicy = new ClaimPolicy(); + claimPolicy.setFieldsToBeDisclosed("{\"name\":0,\"gender\":0,\"age\":0,\"id\":0}"); + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + Map proofMap = copyCredentialPojo.getProof(); + proofMap.remove("signatureValue"); + copyCredentialPojo.setProof(proofMap); + + ResponseData response = + credentialPojoService.createSelectiveCredential(copyCredentialPojo, claimPolicy); + LogUtil.info(logger, "TestCreateSelectiveCredential", response); + + Assert.assertEquals( + ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), response.getErrorCode().intValue()); + Assert.assertNull(response.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByIssuer.java b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByIssuer.java new file mode 100644 index 00000000..66c9e8e7 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByIssuer.java @@ -0,0 +1,593 @@ + + +package com.webank.weid.full.credentialpojo; + +import java.util.Map; + +import mockit.Mock; +import mockit.MockUp; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.impl.WeIdServiceImpl; + +/** + * verifyCredentialPojo method for testing CredentialPojoService. + * + * @author v_wbgyang/rockyxia + */ +public class TestVerifyCredentialByIssuer extends TestBaseService { + + private static final Logger logger = LoggerFactory + .getLogger(TestVerifyCredentialByIssuer.class); + + protected PasswordKey passwordKey = null; + + private static CredentialPojo credentialPojo = null; + + private static CredentialPojo credentialPojoNew = null; + + private static CredentialPojo selectiveCredentialPojo = null; + + + @Override + public synchronized void testInit() { + super.testInit(); + passwordKey = TestBaseUtil.createEcKeyPair(); + if (credentialPojo == null) { + credentialPojo = super.createCredentialPojo(createCredentialPojoArgs); + } + if (credentialPojoNew == null) { + credentialPojoNew = super.createCredentialPojo(createCredentialPojoArgs); + } + if (selectiveCredentialPojo == null) { + selectiveCredentialPojo = super.createSelectiveCredentialPojo(credentialPojo); + } + } + + + /** + * case: verify CredentialPojo success by issuer . + */ + @Test + public void testVerifyCredential_success() { + + ResponseData response = super.verifyCredentialPojo(credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case:verify selective credential success. + */ + @Test + public void testVerifySelectiveCredential_success() { + + ResponseData response = super.verifyCredentialPojo(selectiveCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + + /** + * case: context is null. + */ + @Test + public void testVerifyCredential_contextNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setContext(null); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: context is other string. + */ + @Test + public void testVerifyCredential_contentError() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setContext("xxx"); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: cptId is another with **same** schema. + */ + @Test + public void testVerifyCredential_otherCptId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + + CptBaseInfo cpt = super.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + copyCredentialPojo.setCptId(cpt.getCptId()); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is null. + */ + @Test + public void testVerifyCredential_idNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setId(null); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is not exist. + */ + @Test + public void testVerifyCredential_idNotExist() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setId("xxxxx"); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is other. + */ + @Test + public void testVerifyCredential_OtherId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setId(credentialPojoNew.getId()); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is null. + */ + @Test + public void testVerifyCredential_issuerNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer(null); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is xxxxx. + */ + @Test + public void testVerifyCredential_invalidIsuuer() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer("xxxxxxxxxxx"); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: credentialPojo.issuer is another. + */ + @Test + public void testVerifyCredential_credentialPojoIssuerOther() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer(createWeIdNew.getWeId()); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer and credentialPojo.issuer is different . + */ + @Test + public void testVerifyCredential_otherIssuer() { + + String issuer = createWeIdNew.getWeId(); + + ResponseData response = credentialPojoService.verify(issuer, credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer not exist . + */ + @Test + public void testVerifyCredential_IssuerNotExist() { + String issuer = "did:weid:101:0x39e5e6f663ef77409144014ceb063713b6ffffff"; + + ResponseData response = credentialPojoService + .verify(issuer, selectiveCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate < = 0. + */ + @Test + public void testVerifyCredential_issuanceDateMinus() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(-1L); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate > now. + */ + @Test + public void testVerifyCredential_issuanceDateFuture() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuanceDate(System.currentTimeMillis() + 100000); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate <= 0. + */ + @Test + public void testVerifyCredential_minusExpirationDate() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(-1L); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate <= now. + */ + @Test + public void testVerifyCredentialCase16() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(credentialPojo.getIssuanceDate() - 100000000); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate is null. + */ + @Test + public void testVerifyCredential_expirationDateNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(null); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate is null. + */ + @Test + public void testVerifyCredential_issuanceDateNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(null); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: claim is null. test error,Please add check. + */ + @Test + public void testVerifyCredential_claimNull() { + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setClaim(null); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is empty. + */ + @Test + public void testVerifyCredential_emptySignature() { + CredentialPojo newCredential = copyCredentialPojo(credentialPojo); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, StringUtils.EMPTY); + newCredential.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredential); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is null. + */ + @Test + public void testVerifyCredential_signatureNull() { + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is xxxxxxxxxxxxxxxxxxx. + */ + @Test + public void testVerifyCredential_invalidSignature() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.remove(ParamKeyConstant.PROOF_SIGNATURE); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, "xxxxxxxxxxx"); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature by 122324324324. + */ + @Test + public void testVerifyCredential_signatureRandom() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, "12341234"); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate < now && expirationDate < now && IssuanceDate < expirationDate. + */ + @Test + public void testVerifyCredentialCase27() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(System.currentTimeMillis() - 12000); + copyCredentialPojo.setExpirationDate(System.currentTimeMillis() - 10000); + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: mock CREDENTIAL_WEID_DOCUMENT_ILLEGAL. + */ + @Test + public void testVerifyCredentialCase28() { + + new MockUp() { + @Mock + public ResponseData getWeIdDocument(String weId) { + ResponseData response = new ResponseData(); + response.setErrorCode(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL); + return response; + } + }; + + ResponseData response = super.verifyCredentialPojo(credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof creator and created are null - this is OK. + */ + @Test + public void testVerifyCredential_proofCreatorNull() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_CREATOR, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is not exists. + */ + @Test + public void testVerifyCredentialCase30() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer("did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797441"); + + ResponseData response = super.verifyCredentialPojo(copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof type illegal. + */ + @Test + public void testVerifyCredentialCase31() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_TYPE, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing signature key at all - fail. + */ + @Test + public void testVerifyCredential_removeProofSignature() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.remove(ParamKeyConstant.PROOF_SIGNATURE); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing creator key at all - should be fine. + */ + @Test + public void testVerifyCredential_removeProofCreator() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.remove(ParamKeyConstant.PROOF_CREATOR); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByPublicKey.java b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByPublicKey.java new file mode 100644 index 00000000..8f93a3e1 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialByPublicKey.java @@ -0,0 +1,646 @@ + + +package com.webank.weid.full.credentialpojo; + +import java.util.Map; + +import mockit.Mock; +import mockit.MockUp; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CptBaseInfo; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.impl.WeIdServiceImpl; + +/** + * verifyCredential method for testing CredentialService. + * + * @author v_wbgyang + */ +public class TestVerifyCredentialByPublicKey extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestVerifyCredentialByPublicKey.class); + + protected PasswordKey passwordKey = null; + + private static CredentialPojo credentialPojo = null; + + private static CredentialPojo credentialPojoNew = null; + + private static WeIdPublicKey weIdPublicKey = null; + + private static CredentialPojo selectiveCredentialPojo = null; + + + @Override + public synchronized void testInit() { + super.testInit(); + passwordKey = TestBaseUtil.createEcKeyPair(); + if (credentialPojo == null) { + credentialPojo = super.createCredentialPojo(createCredentialPojoArgs); + } + if (credentialPojoNew == null) { + credentialPojoNew = super.createCredentialPojo(createCredentialPojoArgs); + } + if (selectiveCredentialPojo == null) { + selectiveCredentialPojo = super.createSelectiveCredentialPojo(credentialPojo); + } + if (weIdPublicKey == null) { + weIdPublicKey = createWeIdResultWithSetAttr.getUserWeIdPublicKey(); + } + + } + + + /** + * case: verify CredentialPojo success by public key . + */ + @Test + public void testVerifyCredentialByPubKey_success() { + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, credentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: verify selective CredentialPojo success by public key . + */ + @Test + public void testVerifyCredentialByPubKey_selectiveCredentialSuccess() { + + ResponseData response = super + .verifyCredentialPojo(weIdPublicKey, selectiveCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + + /** + * case: context is null. + */ + @Test + public void testVerifyCredentialByPubKey_contextNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setContext(null); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CONTEXT_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: context is other string. + */ + @Test + public void testVerifyCredential_contentError() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setContext("xxx"); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: cptId is another with **same** schema. + */ + @Test + public void testVerifyCredential_otherCptId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + CptBaseInfo cpt = super.registerCpt(createWeIdResultWithSetAttr, registerCptArgs); + copyCredentialPojo.setCptId(cpt.getCptId()); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is null. + */ + @Test + public void testVerifyCredential_idNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setId(null); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is not exist. + */ + @Test + public void testVerifyCredential_idNotExist() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setId("xxxxx"); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ID_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: id is other. + */ + @Test + public void testVerifyCredential_OtherId() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setId(credentialPojoNew.getId()); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "testVerifyCredentialByPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is null. + */ + @Test + public void testVerifyCredential_issuerNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuer(null); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is xxxxx. + */ + @Test + public void testVerifyCredential_invalidIsuuer() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer("xxxxxxxxxxx"); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: credentialPojo.issuer is another. + */ + @Test + public void testVerifyCredential_credentialPojoIssuerOther() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setIssuer(createWeIdNew.getWeId()); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: publickey and credentialPojo.issuer.publickey is different . + */ + @Test + public void testVerifyCredential_otherIssuer() { + + WeIdPublicKey otherPublicKey = createWeIdNew.getUserWeIdPublicKey(); + + ResponseData response = credentialPojoService.verify(otherPublicKey, + credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: public key is not exist . + */ + @Test + public void testVerifyCredential_pubKeyNull() { + + ResponseData response = credentialPojoService.verify(new WeIdPublicKey(), + credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_PUBLIC_KEY_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate < = 0. + */ + @Test + public void testVerifyCredential_issuanceDateMinus() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(-1L); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate > now. + */ + @Test + public void testVerifyCredential_issuanceDateFuture() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(System.currentTimeMillis() + 100000); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUANCE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate <= 0. + */ + @Test + public void testVerifyCredential_minusExpirationDate() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(-1L); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate <= now. + */ + @Test + public void testVerifyCredential_expirationDatePassed() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(credentialPojo.getIssuanceDate() - 100000000); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: expirationDate is null. + */ + @Test + public void testVerifyCredential_expirationDateNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setExpirationDate(null); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRE_DATE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate is null. + */ + @Test + public void testVerifyCredential_issuanceDateNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(null); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: claim is null. test error,Please add check. + */ + @Test + public void testVerifyCredential_claimNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setClaim(null); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: claim is null. test error,. + */ + @Test + public void testVerifyCredential_selectiveCredentialClaimNull() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(selectiveCredentialPojo); + copyCredentialPojo.setClaim(null); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_CLAIM_NOT_EXISTS.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is empty. + */ + @Test + public void testVerifyCredential_emptySignature() { + CredentialPojo newCredential = copyCredentialPojo(credentialPojo); + Map proof = newCredential.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, StringUtils.EMPTY); + newCredential.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredential); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is null. + */ + @Test + public void testVerifyCredential_signatureNull() { + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature is xxxxxxxxxxxxxxxxxxx. + */ + @Test + public void testVerifyCredential_invalidSignature() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, "xxxxxxxxxxx"); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: signature by 122324324324. + */ + @Test + public void testVerifyCredential_signatureRnadom() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_SIGNATURE, "12341234"); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: IssuanceDate < now && expirationDate < now && IssuanceDate < expirationDate. + */ + @Test + public void testVerifyCredentialCase27() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + copyCredentialPojo.setIssuanceDate(System.currentTimeMillis() - 12000); + copyCredentialPojo.setExpirationDate(System.currentTimeMillis() - 10000); + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_EXPIRED.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: mock CREDENTIAL_WEID_DOCUMENT_ILLEGAL. + */ + @Test + public void testVerifyCredentialCase28() { + + new MockUp() { + @Mock + public ResponseData getWeIdDocument(String weId) { + ResponseData response = new ResponseData(); + response.setErrorCode(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL); + return response; + } + }; + + ResponseData response = super.verifyCredentialPojo(credentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_WEID_DOCUMENT_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof creator and created are null - this is OK. + */ + @Test + public void testVerifyCredential_proofCreatorNull() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_CREATOR, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: issuer is not exists. + */ + @Test + public void testVerifyCredential_invalidIssuer() { + + CredentialPojo copyCredentialPojo = copyCredentialPojo(credentialPojo); + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), "ffff"); + copyCredentialPojo.setIssuer(weId); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + copyCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof type illegal. + */ + @Test + public void testVerifyCredentialCase31() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.put(ParamKeyConstant.PROOF_TYPE, null); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_TYPE_ILLEGAL.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing signature key at all - fail. + */ + @Test + public void testVerifyCredential_removeProofCredentialSignature() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.remove(ParamKeyConstant.PROOF_SIGNATURE); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: proof is missing creator key at all - should be fine. + */ + @Test + public void testVerifyCredentialCase33() { + + CredentialPojo newCredentialPojo = copyCredentialPojo(credentialPojo); + Map proof = newCredentialPojo.getProof(); + proof.remove(ParamKeyConstant.PROOF_CREATOR); + newCredentialPojo.setProof(proof); + + ResponseData response = super.verifyCredentialPojo(weIdPublicKey, + newCredentialPojo); + LogUtil.info(logger, "verifyCredential", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithPresentation.java b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithPresentation.java new file mode 100644 index 00000000..d06bc501 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithPresentation.java @@ -0,0 +1,201 @@ +package com.webank.weid.full.credentialpojo; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.protocol.base.*; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TestVerifyCredentialWithPresentation extends TestBaseTransportation { + + private static final Logger logger = + LoggerFactory.getLogger(TestCreatePresentation.class); + + private static CredentialPojo credentialPojoNew = null; + + private static List credentialList = new ArrayList<>(); + + private static PresentationPolicyE presentationPolicyE + = PresentationPolicyE.create("policy.json"); + + private static Challenge challenge = null; + + private static PresentationE presentationE = null; + + //test for pdf presentation verify + private static CredentialPojo credentialPojoNew1 = null; + + private static List credentialList1 = new ArrayList<>(); + + private static PresentationPolicyE presentationPolicyE1 + = PresentationPolicyE.create("test-spectpl-policy.json"); + + private static Challenge challenge1 = null; + + private static PresentationE presentationE1 = null; + + @Override + public synchronized void testInit() { + + super.testInit(); + + if (credentialPojoNew == null) { + credentialPojoNew = super.createCredentialPojo(createCredentialPojoArgsNew); + } + if (presentationPolicyE != null) { + presentationPolicyE = PresentationPolicyE.create("policy.json"); + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy = policyMap.get(1000); + policyMap.remove(1000); + policyMap.put(createCredentialPojoArgs.getCptId(), cliamPolicy); + } + if (challenge == null) { + challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis())); + } + + if (credentialList == null || credentialList.size() == 0) { + credentialList.add(credentialPojo); + } + + if (presentationE == null) { + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + presentationE = response.getResult(); + } + + //init for pdf presentation verify + super.testInitSpecTplCpt(); + + if (credentialPojoNew1 == null) { + credentialPojoNew1 = super.createCredentialPojo(createCredentialPojoArgs4); + } + if (presentationPolicyE1 != null) { + presentationPolicyE1 = PresentationPolicyE.create("test-spectpl-policy.json"); + presentationPolicyE1.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap1 = presentationPolicyE1.getPolicy(); + ClaimPolicy cliamPolicy1 = policyMap1.get(1005); + policyMap1.remove(1005); + policyMap1.put(createCredentialPojoArgs4.getCptId(), cliamPolicy1); + } + if (challenge1 == null) { + challenge1 = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis())); + } + + if (credentialList1 == null || credentialList1.size() == 0) { + credentialList1.add(credentialPojoNew1); + } + if (presentationE1 == null) { + ResponseData response1 = credentialPojoService.createPresentation( + credentialList1, + presentationPolicyE1, + challenge1, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + presentationE1 = response1.getResult(); + } + + + } + + /** + * verify credential pojo with presention successs. + */ + @Test + public void testVerfiyCredential_suceess() { + + ResponseData response = credentialPojoService.verify( + credentialPojo.getIssuer(), + presentationPolicyE, + challenge, + presentationE); + LogUtil.info(logger, "testVerfiyCredentialWithPresention", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + } + + /** + * verify presentation from pdf transportation. + */ + /*@Test + @Ignore + public void testVerifyPdfPresentation_fail() { + + //序列化PDF,生成包含PDF信息的byte[] + ResponseData retSerialize = TransportationFactory.newPdfTransportation() + .serializeWithTemplate( + presentationE1, + new ProtocolProperty(EncodeType.ORIGINAL), + "src/test/resources/test-template.pdf"); + LogUtil.info(logger, "serialize", retSerialize); + + //反序列化PDF数组为PresentationE + ResponseData retDeserialize = TransportationFactory.newPdfTransportation() + .deserialize(retSerialize.getResult(), PresentationE.class, weIdAuthentication); + LogUtil.info(logger, "deserialize", retDeserialize); + + ResponseData response = credentialPojoService.verify( + credentialPojoNew1.getIssuer(), + presentationPolicyE1, + challenge1, + retDeserialize.getResult()); + LogUtil.info(logger, "testVerfiyCredentialWithPresention", response); + Assert.assertEquals( + ErrorCode.CREDENTIAL_USE_VERIFY_FUNCTION_ERROR.getCode(), + response.getErrorCode().intValue()); + }*/ + + /** + * verify presentation from pdf transportation. + */ + /*@Test + @Ignore + public void testVerifyPdfPresentation_success() { + PdfTransportationImpl pdfTransportation = new PdfTransportationImpl(); + + //序列化PDF,生成包含PDF信息的byte[] + ResponseData retSerialize = TransportationFactory.newPdfTransportation() + .serializeWithTemplate( + presentationE1, + new ProtocolProperty(EncodeType.ORIGINAL), + "src/test/resources/test-template.pdf"); + LogUtil.info(logger, "serialize", retSerialize); + + //反序列化PDF数组为PresentationE + ResponseData retDeserialize = TransportationFactory.newPdfTransportation() + .deserialize( + retSerialize.getResult(), + PresentationE.class, + weIdAuthentication); + LogUtil.info(logger, "deserialize", retDeserialize); + + ResponseData response = credentialPojoService.verifyPresentationFromPdf( + "src/test/resources/test-template.pdf", + retSerialize.getResult(), + credentialPojoNew1.getIssuer(), + presentationPolicyE1, + challenge1, + retDeserialize.getResult()); + LogUtil.info(logger, "testVerfiyCredentialWithPresention", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + }*/ +} diff --git a/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithSpecifiedPubKey.java b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithSpecifiedPubKey.java new file mode 100644 index 00000000..72127918 --- /dev/null +++ b/src/test/java/com/webank/weid/full/credentialpojo/TestVerifyCredentialWithSpecifiedPubKey.java @@ -0,0 +1,156 @@ + + +package com.webank.weid.full.credentialpojo; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.CredentialWrapper; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.CreateCredentialArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * verifyCredentialWithSpecifiedPubKey method for testing CredentialService. + * + * @author v_wbgyang + */ +public class TestVerifyCredentialWithSpecifiedPubKey extends TestBaseService { + + private static final Logger logger = + LoggerFactory.getLogger(TestVerifyCredentialWithSpecifiedPubKey.class); + + protected PasswordKey newPasswordKey = null; + + @Override + public synchronized void testInit() { + super.testInit(); + newPasswordKey = TestBaseUtil.createEcKeyPair(); + } + + /** + * case: verifyCredentialWithSpecifiedPubKey success. + */ + @Test + public void testVerifyCredentialWithSpecifiedPubKeyCase1() { + + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); + + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(newPasswordKey.getPublicKey()); + ResponseData response = + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + } + + /** + * case: verifyCredentialWithSpecifiedPubKey fail. + */ + @Test + public void testVerifyCredentialWithSpecifiedPubKeyCase2() { + + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); + + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(passwordKey.getPublicKey()); + + ResponseData response = + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); + + Assert.assertTrue(ErrorCode.CREDENTIAL_SIGNATURE_BROKEN.getCode() + == response.getErrorCode().intValue() || ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode() + == response.getErrorCode().intValue() || response.getErrorCode().intValue() + == ErrorCode.CREDENTIAL_EXCEPTION_VERIFYSIGNATURE.getCode()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: verifyCredentialWithSpecifiedPubKey publicKey is null. + */ + @Test + public void testVerifyCredentialWithSpecifiedPubKeyCase3() { + + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); + + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + + ResponseData response = + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, null); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + /** + * case: verifyCredentialArgs is null. + */ + @Test + public void testVerifyCredentialWithSpecifiedPubKeyCase4() { + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(newPasswordKey.getPublicKey()); + ResponseData response = + credentialService.verifyCredentialWithSpecifiedPubKey(null, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); + + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + + + /** + * case: verifyCredentialWithSpecifiedPubKey publicKey is "xxxxxxxxxxxxx". + */ + @Test + public void testVerifyCredentialWithSpecifiedPubKeyCase7() { + + CreateCredentialArgs createCredentialArgs = + TestBaseUtil.buildCreateCredentialArgs(createWeIdResultWithSetAttr); + createCredentialArgs.setCptId(cptBaseInfo.getCptId()); + + createCredentialArgs.getWeIdPrivateKey().setPrivateKey(newPasswordKey.getPrivateKey()); + + CredentialWrapper credentialWrapper = super.createCredential(createCredentialArgs); + + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey("xxxxxxxxxxxxx"); + + ResponseData response = + credentialService.verifyCredentialWithSpecifiedPubKey(credentialWrapper, weIdPublicKey); + LogUtil.info(logger, "verifyCredentialWithSpecifiedPubKey", response); + + Assert.assertEquals(ErrorCode.CREDENTIAL_ERROR.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/evidence/TestCreateEvidence.java b/src/test/java/com/webank/weid/full/evidence/TestCreateEvidence.java new file mode 100644 index 00000000..7625b5b6 --- /dev/null +++ b/src/test/java/com/webank/weid/full/evidence/TestCreateEvidence.java @@ -0,0 +1,706 @@ + + +package com.webank.weid.full.evidence; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.EvidenceInfo; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.request.TransactionArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.service.local.EvidenceServiceLocal; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; + +import com.webank.weid.util.PropertyUtils; +import com.webank.weid.util.WeIdUtils; +import org.apache.commons.lang3.StringUtils; +import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.v3.crypto.CryptoSuite; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * Test CreateEvidence. + * + * @author v_wbgyang + */ +public class TestCreateEvidence extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestCreateEvidence.class); + + private static volatile Credential credential = null; + + @Override + public synchronized void testInit() { + super.testInit(); + if (credential == null) { + credential = super.createCredential(createCredentialArgs).getCredential(); + } + } + + /** + * case1: credential issuer and private key belong the same weId. + */ + @Test + public void testCreateEvidence_success() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = evidenceService.generateHash(credential).getResult().getHash(); + // Direct call of add - should fail + ResponseData addResp = evidenceService.addLogByHash(hash, "3.23", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertFalse(addResp.getResult()); + // Must create evidence and sign first! + ResponseData response = evidenceService.createEvidence(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + evidenceService.addLogByHash(hash, "1.23", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + evidenceService.addLogByHash(hash, "13.15", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertTrue(!response.getResult().isEmpty()); + ResponseData eviInfo = evidenceService.getEvidence(hash); + EvidenceInfo evidenceInfo = eviInfo.getResult(); + Assert.assertTrue(evidenceInfo.getCredentialHash().equalsIgnoreCase(hash)); + String signerWeId = tempCreateWeIdResultWithSetAttr.getWeId(); + Assert.assertTrue(evidenceInfo.getSigners().contains(WeIdUtils.convertWeIdToAddress(signerWeId))); + Assert.assertEquals(evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signerWeId)).getLogs().size(), 3); + Assert.assertTrue( + evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signerWeId)).getLogs().get(1).equals("1.23")); + Assert.assertTrue( + evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signerWeId)).getLogs().get(2).equals("13.15")); + ResponseData resp = evidenceService + .verifySigner(credential, evidenceInfo, signerWeId); + Assert.assertTrue(resp.getResult()); + } + + @Test + public void testEvidenceManipulationFailures() { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + CreateWeIdDataResult cwdr = createWeIdWithSetAttr(); + // Get another signer here: + String tempSigner = cwdr.getWeId(); + evidenceService + .createRawEvidenceWithSpecificSigner(hash, credential.getSignature(), "temp-log", + DateUtils.getNoMillisecondTimeStamp(), credential.getId(), tempSigner, privateKey); + ResponseData eviResp = evidenceService.getEvidence(hash); + Assert.assertNotNull(eviResp.getResult()); + ResponseData verifyResp = evidenceService + .verifySigner(credential, eviResp.getResult(), tempSigner); + // Here it should fail, since: signer's sig ! from privatekey, and issuer != signer + Assert.assertFalse(verifyResp.getResult()); + Assert.assertEquals(verifyResp.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_ISSUER_MISMATCH.getCode()); + + //---- + credential.setId(UUID.randomUUID().toString()); + credential.setIssuer(tempSigner); + hash = credential.getHash(); + // Get another signer here: + evidenceService.createRawEvidenceWithSpecificSigner(hash, credential.getSignature(), + "temp-log", DateUtils.getNoMillisecondTimeStamp(), credential.getId(), tempSigner, + privateKey); + eviResp = evidenceService.getEvidence(hash); + Assert.assertNotNull(eviResp.getResult()); + verifyResp = evidenceService.verifySigner(credential, eviResp.getResult(), tempSigner); + // Here it should fail, since: signer's sig ! from privatekey + Assert.assertFalse(verifyResp.getResult()); + Assert.assertEquals(verifyResp.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_VERIFY_FAIL.getCode()); + + //---- + credential.setId(UUID.randomUUID().toString()); + credential.setIssuer(tempSigner); + hash = credential.getHash(); + // Get another signer here: + evidenceService.createRawEvidenceWithSpecificSigner(hash, credential.getSignature(), + "temp-log", DateUtils.getNoMillisecondTimeStamp(), credential.getId(), tempSigner, + cwdr.getUserWeIdPrivateKey().getPrivateKey()); + eviResp = evidenceService.getEvidence(hash); + Assert.assertNotNull(eviResp.getResult()); + verifyResp = evidenceService.verifySigner(credential, eviResp.getResult(), tempSigner); + // Here it should still fail, since: signer's sig ! from privatekey + Assert.assertFalse(verifyResp.getResult()); + } + + @Test + public void testCreateEvidenceDupAndNonExist() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = evidenceService.generateHash(credential).getResult().getHash(); + ResponseData createResp1 = evidenceService.createEvidence(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + ResponseData createResp2 = evidenceService.createEvidence(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertEquals(createResp1.getResult(), hash); + Assert.assertEquals(createResp2.getResult(), StringUtils.EMPTY); + Assert.assertEquals(createResp2.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_EVIDENCE_ALREADY_EXISTS.getCode()); + createResp2 = evidenceService.createEvidenceWithLogAndCustomKey(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey(), "a", credential.getId()); + Assert.assertEquals(createResp2.getResult(), StringUtils.EMPTY); + Assert.assertEquals(createResp2.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_EVIDENCE_ALREADY_EXISTS.getCode()); + credential.setId(UUID.randomUUID().toString()); + ResponseData addResp1 = evidenceService.addLogByHash(credential.getHash(), "a", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertEquals(addResp1.getResult(), false); + Assert.assertEquals(addResp1.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST.getCode()); + ResponseData addResp2 = evidenceService.addSignatureAndLogByHash( + credential.getHash(), "a", tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertEquals(addResp2.getResult(), false); + Assert.assertEquals(addResp2.getErrorCode().intValue(), + ErrorCode.CREDENTIAL_EVIDENCE_NOT_EXIST.getCode()); + } + + @Test + public void testCreateEvidence_MultipleSigners() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = evidenceService.generateHash(credential).getResult().getHash(); + ResponseData createResp1 = evidenceService.createEvidence(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + ResponseData addResp1 = evidenceService.addLogByHash(hash, "1.23", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + ResponseData addResp2 = evidenceService.addLogByHash(hash, "13.15", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + // Another guy signs + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr2 = createWeIdWithSetAttr(); + ResponseData createResp2 = evidenceService.addSignatureAndLogByHash( + credential.getHash(), "empty log", tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey()); + ResponseData addResp3 = evidenceService.addLogByHash(hash, "abc", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey()); + ResponseData addResp4 = evidenceService.addLogByHash(hash, "eef", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey()); + // Now check + ResponseData eviInfo = evidenceService.getEvidence(hash); + EvidenceInfo evidenceInfo = eviInfo.getResult(); + String signer1 = tempCreateWeIdResultWithSetAttr.getWeId(); + String signer2 = tempCreateWeIdResultWithSetAttr2.getWeId(); + Assert.assertEquals(evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer1)).getLogs().size(), 3); + Assert.assertEquals(evidenceInfo.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer2)).getLogs().size(), 3); + ResponseData resp = evidenceService + .verifySigner(credential, evidenceInfo, signer1); + Assert.assertTrue(resp.getResult()); + resp = evidenceService.verifySigner(credential, evidenceInfo, signer2); + // here it should be false since signer changed + Assert.assertFalse(resp.getResult()); + } + + @Test + public void testCreateEvidence_CustomKeyHappyPath() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = evidenceService.generateHash(credential).getResult().getHash(); + String credId = credential.getId(); + ResponseData cresp = evidenceService.createEvidenceWithLogAndCustomKey( + credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey(), + "Ironman", + hash + ); + Assert.assertTrue(StringUtils.isEmpty(cresp.getResult())); + evidenceService.createEvidenceWithLogAndCustomKey( + credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey(), + "Ironman", + credId + ); + ResponseData eviHash = evidenceService.getEvidence(hash); + EvidenceInfo evi1 = eviHash.getResult(); + ResponseData eviCustomKey = evidenceService.getEvidenceByCustomKey(credId); + EvidenceInfo evi2 = eviCustomKey.getResult(); + Assert.assertEquals(evi1.getSigners(), evi2.getSigners()); + Assert.assertEquals(evi1.getSignatures(), evi2.getSignatures()); + String signer = tempCreateWeIdResultWithSetAttr.getWeId(); + Assert.assertEquals(evi1.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs(), + evi2.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs()); + evidenceService.addLogByHash(hash, "Insane", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + evidenceService.addLogByCustomKey(null, credId, "Difficult", + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + evi2 = evidenceService.getEvidenceByCustomKey(credId).getResult(); + Assert.assertEquals(evi2.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs().size(), 3); + List list = Arrays.asList("Ironman", "Insane", "Difficult"); + Assert.assertEquals(evi2.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs(), list); + } + + @Test + public void testCreateEvidence_CustomKeyMultiSignerMultiTimes() { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + Assert.assertNotNull(credential); + credential.setId(UUID.randomUUID().toString()); + String credId = credential.getId(); + List list = new ArrayList<>(); + String log = "X:112.5,Y:97.6"; + list.add(log); + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + ResponseData resp = evidenceService.createEvidenceWithLogAndCustomKey( + credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey(), + log, + credId + ); + Assert.assertTrue(!StringUtils.isEmpty(resp.getResult())); + log = "X:122.5,Y:94.3"; + list.add(log); + ResponseData addResp = evidenceService.addLogByCustomKey( + null, + credId, + log, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + log = "X:102.5,Y:99.1"; + list.add(log); + addResp = evidenceService.addLogByCustomKey( + null, + credId, + log, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + log = "X:0,Y:0"; + list.add(log); + addResp = evidenceService.addLogByHash(credential.getHash(), log, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertTrue(addResp.getResult()); + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr2 = createWeIdWithSetAttr(); + addResp = evidenceService.addLogByCustomKey( + null, + credId, + "Age:11", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + addResp = evidenceService.addSignatureAndLogByCustomKey( + null, + credId, + "Age:22", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + addResp = evidenceService.addSignatureAndLogByCustomKey( + null, + credId, + "Age:33", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + addResp = evidenceService.addLogByCustomKey( + null, + credId, + "Age:44", + tempCreateWeIdResultWithSetAttr2.getUserWeIdPrivateKey() + ); + Assert.assertTrue(addResp.getResult()); + ResponseData eviCustomKey = evidenceService.getEvidenceByCustomKey(credId); + EvidenceInfo evi = eviCustomKey.getResult(); + String signer = tempCreateWeIdResultWithSetAttr.getWeId(); + Assert.assertNotNull(evi.getSignInfo()); + Assert.assertNotNull(evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer))); + Assert.assertEquals(evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs(), list); + String signer2 = tempCreateWeIdResultWithSetAttr2.getWeId(); + Assert.assertTrue(evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer2)).getLogs().contains("Age:22") + && evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer2)).getLogs().size() == 4); + } + + @Test + public void testAddLogsAll() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String credId = credential.getId(); + String log = DataToolUtils.serialize(credential); + evidenceService.createEvidenceWithLogAndCustomKey( + credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey(), + log, + credId + ); + ResponseData eviResp = evidenceService.getEvidenceByCustomKey(credId); + EvidenceInfo evi = eviResp.getResult(); + String signer = tempCreateWeIdResultWithSetAttr.getWeId(); + Assert.assertTrue(evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs().contains(log)); + int length = 50; // Up to 2M can still work + StringBuffer outputBuffer = new StringBuffer(length); + for (int i = 0; i < length; i++) { + outputBuffer.append("a"); + } + log = outputBuffer.toString(); + evidenceService.addLogByCustomKey(null, credId, log, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + evi = evidenceService.getEvidenceByCustomKey(credId).getResult(); + Assert.assertNotNull(evi); + Assert.assertTrue(evi.getSignInfo().get(WeIdUtils.convertWeIdToAddress(signer)).getLogs().contains(log)); + } + + @Test + public void testBatchCreate() throws Exception { + List hashValues = new ArrayList<>(); + List signatures = new ArrayList<>(); + List timestamps = new ArrayList<>(); + List signers = new ArrayList<>(); + List logs = new ArrayList<>(); + List customKeys = new ArrayList<>(); + int batchSize = 100; + for (int i = 0; i < batchSize; i++) { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + hashValues.add(credential.getHash()); + signatures.add(DataToolUtils.SigBase64Serialization(DataToolUtils.signToRsvSignature(hash, privateKey))); + timestamps.add(System.currentTimeMillis()); + signers.add(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + logs.add("test log" + i); + if (i % 2 == 1) { + customKeys.add(String.valueOf(System.currentTimeMillis())); + } else { + customKeys.add(StringUtils.EMPTY); + } + } + + //EvidenceServiceEngine engine = EngineFactory.createEvidenceServiceEngine(com.webank.weid.blockchain.service.fisco.BaseService.masterGroupId); + com.webank.weid.blockchain.rpc.EvidenceService evidenceBlockchainService; + if (PropertyUtils.getProperty("deploy.style").equals("blockchain")) { + evidenceBlockchainService = new com.webank.weid.blockchain.service.impl.EvidenceServiceImpl(); + } else { + // default database + evidenceBlockchainService = new EvidenceServiceLocal(); + } + // raw creation + Long start = System.currentTimeMillis(); + Long end = System.currentTimeMillis(); + System.out.println("Batch creation w/ size: " + batchSize + " takes time (ms): " + (String + .valueOf(end - start))); + List booleans = evidenceBlockchainService + .batchCreateEvidence(hashValues, signatures, logs, timestamps, signers, privateKey).getResult(); + Assert.assertEquals(booleans.size(), hashValues.size()); + Boolean result = true; + for (int i = 0; i < booleans.size(); i++) { + result = result && booleans.get(i); + } + Assert.assertTrue(result); + + // test illegal hashs + List faultyHashValues = new ArrayList<>(); + faultyHashValues.addAll(hashValues); + faultyHashValues.set(1, null); + booleans = evidenceBlockchainService + .batchCreateEvidence(faultyHashValues, signatures, logs, timestamps, signers, privateKey).getResult(); + Assert.assertFalse(booleans.get(1)); + + // custom keys (semi filled) + start = System.currentTimeMillis(); + end = System.currentTimeMillis(); + System.out.println( + "Batch creation w/ custom keys and size: " + batchSize + " takes time (ms): " + (String + .valueOf(end - start))); + booleans = evidenceBlockchainService + .batchCreateEvidenceWithCustomKey(hashValues, signatures, logs, timestamps, signers, + customKeys, privateKey).getResult(); + Assert.assertEquals(booleans.size(), hashValues.size()); + result = true; + // All hashes already existed, so all fail. + for (int i = 0; i < booleans.size(); i++) { + result = result && booleans.get(i).booleanValue(); + } + Assert.assertFalse(result); + + // Check get + String hash0 = hashValues.get(0); + String hash1 = hashValues.get(1); + String key1 = customKeys.get(1); + EvidenceInfo evidenceInfo0 = evidenceService.getEvidence(hash0).getResult(); + EvidenceInfo evidenceInfo1 = evidenceService.getEvidence(hash1).getResult(); + Assert.assertNotNull(evidenceInfo0); + Assert.assertNotNull(evidenceInfo1); + } + + /** + * This test can only be invoked when using multi-group with group = 1 and 2. + */ + public void testBatchCreateMultiGroup() throws IOException { + int batchSize = 100; + List transactionArgsList = new ArrayList<>(); + for (int i = 0; i < batchSize; i++) { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + TransactionArgs args = new TransactionArgs(); + args.setMethod("createEvidence"); + List argList = new ArrayList<>(); + argList.add(credential.getHash()); + argList.add(DataToolUtils.SigBase64Serialization(DataToolUtils.signToRsvSignature(hash, privateKey))); + argList.add("test log" + i); + argList.add(DateUtils.getNoMillisecondTimeStampString()); + argList + .add(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + if (i % 2 == 1) { + argList.add("2"); + } + args.setArgs(String.join(",", argList)); + transactionArgsList.add(args); + } + /*if ("2".equals(com.webank.weid.blockchain.service.fisco.BaseService.getVersion())) { + CryptoKeyPair cryptoKeyPair = com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.getKeyPairFactory() + .createKeyPair(new BigInteger(privateKey)); + for (int i = 0; i < batchSize; i++) { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + TransactionArgs args = new TransactionArgs(); + args.setMethod("createEvidence"); + List argList = new ArrayList<>(); + argList.add(credential.getHash()); + argList.add(com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.sign(hash, cryptoKeyPair).convertToString()); + argList.add("test log" + i); + argList.add(DateUtils.getNoMillisecondTimeStampString()); + argList + .add(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + if (i % 2 == 1) { + argList.add("2"); + } + args.setArgs(String.join(",", argList)); + transactionArgsList.add(args); + } + } else { + CryptoSuite cryptoSuite = new CryptoSuite(com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.getCryptoTypeConfig()); + org.fisco.bcos.sdk.v3.crypto.keypair.CryptoKeyPair cryptoKeyPair = + cryptoSuite.getKeyPairFactory() + .createKeyPair(new BigInteger(privateKey)); + for (int i = 0; i < batchSize; i++) { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + TransactionArgs args = new TransactionArgs(); + args.setMethod("createEvidence"); + List argList = new ArrayList<>(); + argList.add(credential.getHash()); + argList.add(cryptoSuite.sign(hash, cryptoKeyPair).convertToString()); + argList.add("test log" + i); + argList.add(DateUtils.getNoMillisecondTimeStampString()); + argList + .add(WeIdUtils.getWeIdFromPrivateKey(privateKey)); + if (i % 2 == 1) { + argList.add("2"); + } + args.setArgs(String.join(",", argList)); + transactionArgsList.add(args); + } + }*/ + //OffLineBatchTask task = new OffLineBatchTask(); + //task.sendBatchTransaction(transactionArgsList); + } + + @Test + public void testRawCreation() { + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = credential.getHash(); + String sig = "testSig"; + String log = "abc"; + String customKey = credential.getId(); + ResponseData resp = evidenceService + .createRawEvidenceWithCustomKey(hash, sig, log, System.currentTimeMillis(), customKey, + privateKey); + Assert.assertTrue(resp.getResult()); + ResponseData eviResp = evidenceService.getEvidenceByCustomKey(customKey); + Assert.assertTrue(eviResp.getResult().getSignatures().get(0).equalsIgnoreCase(sig)); + + //---- + credential.setId(UUID.randomUUID().toString()); + hash = credential.getHash(); + String signer1 = createWeIdResultWithSetAttr.getWeId(); + resp = evidenceService.createRawEvidenceWithSpecificSigner(hash, sig, log, + System.currentTimeMillis(), StringUtils.EMPTY, signer1, privateKey); + Assert.assertTrue(resp.getResult()); + eviResp = evidenceService.getEvidence(hash); + Assert.assertTrue(hash.equalsIgnoreCase(eviResp.getResult().getCredentialHash())); + Assert.assertTrue(eviResp.getResult().getSigners().size() == 1); + Assert.assertTrue(eviResp.getResult().getSigners().get(0).equalsIgnoreCase(WeIdUtils.convertWeIdToAddress(signer1))); + + //---- + credential.setId(UUID.randomUUID().toString()); + hash = credential.getHash(); + resp = evidenceService.createRawEvidenceWithSpecificSigner(hash, sig, log, + System.currentTimeMillis(), credential.getId(), signer1, privateKey); + Assert.assertTrue(resp.getResult()); + eviResp = evidenceService.getEvidence(hash); + ResponseData eviResp2 = + evidenceService.getEvidenceByCustomKey(credential.getId()); + Assert.assertEquals(eviResp.getResult().getCredentialHash(), + eviResp2.getResult().getCredentialHash()); + Assert.assertTrue(hash.equalsIgnoreCase(eviResp.getResult().getCredentialHash())); + Assert.assertTrue(eviResp.getResult().getSigners().size() == 1); + Assert.assertTrue(eviResp.getResult().getSigners().get(0).equalsIgnoreCase(WeIdUtils.convertWeIdToAddress(signer1))); + } + + /** + * Test status: revoked. + */ + @Test + public void testSetRevokeStatus() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = createWeId(); + CredentialPojo credential = createCredentialPojo(createCredentialPojoArgs); + credential.setId(UUID.randomUUID().toString()); + String hash = evidenceService.generateHash(credential).getResult().getHash(); + ResponseData createResp1 = evidenceService.createEvidence(credential, + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication + .setWeIdPrivateKey(tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + ResponseData revokeResp = evidenceService.revoke(credential, weIdAuthentication); + Assert.assertTrue(revokeResp.getResult()); + ResponseData getResp = evidenceService.getEvidence(credential.getHash()); + Assert.assertNotNull(getResp.getResult()); + Assert.assertTrue(getResp.getResult().getSignInfo() + .get(WeIdUtils.convertWeIdToAddress(tempCreateWeIdResultWithSetAttr.getWeId())).getRevoked()); + revokeResp = evidenceService.unRevoke(credential, weIdAuthentication); + getResp = evidenceService.getEvidence(credential.getHash()); + Assert.assertFalse(getResp.getResult().getSignInfo() + .get(WeIdUtils.convertWeIdToAddress(tempCreateWeIdResultWithSetAttr.getWeId())).getRevoked()); + revokeResp = evidenceService.revoke(credential, weIdAuthentication); + getResp = evidenceService.getEvidence(credential.getHash()); + Assert.assertTrue(getResp.getResult().getSignInfo() + .get(WeIdUtils.convertWeIdToAddress(tempCreateWeIdResultWithSetAttr.getWeId())).getRevoked()); + EvidenceInfo evidenceInfo = getResp.getResult(); + Assert.assertFalse(evidenceService.isRevoked( + evidenceInfo, createWeIdResultWithSetAttr.getWeId()).getResult()); + Assert.assertTrue(evidenceService.isRevoked( + evidenceInfo, tempCreateWeIdResultWithSetAttr.getWeId()).getResult()); + } + + /** + * case3: weIdPrivateKey is null. + */ + @Test + public void testCreateEvidence_priKeyNull() { + ResponseData response = evidenceService + .createEvidence(credential, null); + LogUtil.info(logger, "createEvidence", response); + + Assert.assertEquals( + ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(!response.getResult().isEmpty()); + } + + /** + * case5: privateKey is null. + */ + @Test + public void testCreateEvidence_privateKeyNull() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey().setPrivateKey(null); + + ResponseData response = evidenceService + .createEvidence(credential, tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + LogUtil.info(logger, "createEvidence", response); + Assert.assertEquals( + ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(!response.getResult().isEmpty()); + } + + /** + * case6: privateKey is xxxxx. + */ + @Test + public void testCreateEvidenceCase05() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey().setPrivateKey("xxxxx"); + + ResponseData response = evidenceService + .createEvidence(credential, tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + LogUtil.info(logger, "createEvidence", response); + Assert.assertEquals( + ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(!response.getResult().isEmpty()); + } + + /** + * case6: privateKey is blank. + */ + @Test + public void testCreateEvidence_priKeyBlank() { + CreateWeIdDataResult tempCreateWeIdResultWithSetAttr = + super.copyCreateWeId(createWeIdResultWithSetAttr); + tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey().setPrivateKey(""); + + ResponseData response = evidenceService + .createEvidence(credential, tempCreateWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + LogUtil.info(logger, "createEvidence", response); + Assert.assertEquals( + ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertFalse(!response.getResult().isEmpty()); + } + + /** + * Case: generate hash value. + */ + @Test + public void testGenerateHash() throws Exception { + // Credential and CredentialPojo + Assert.assertTrue(evidenceService.generateHash(credential).getResult().getHash() + .equalsIgnoreCase(credential.getHash())); + Assert.assertTrue(evidenceService.generateHash(credentialPojo).getResult().getHash() + .equalsIgnoreCase(credentialPojo.getHash())); + Assert.assertTrue(evidenceService.generateHash(selectiveCredentialPojo).getResult() + .getHash().equalsIgnoreCase(selectiveCredentialPojo.getHash())); + // Test file + String path = TestCreateEvidence.class + .getClassLoader().getResource("test-template.pdf").getPath(); + File file = new File(path); + String fileHash = evidenceService.generateHash(file).getResult().getHash(); + Assert.assertFalse(StringUtils.isEmpty(fileHash)); + // Support GBK and UTF-8 encoding here - they will yield different hash values, though + path = TestCreateEvidence.class.getClassLoader().getResource("org1.txt").getPath(); + file = new File(path); + fileHash = evidenceService.generateHash(file).getResult().getHash(); + Assert.assertFalse(StringUtils.isEmpty(fileHash)); + path = TestCreateEvidence.class.getClassLoader().getResource("test-hash-pic.png").getPath(); + file = new File(path); + fileHash = evidenceService.generateHash(file).getResult().getHash(); + Assert.assertFalse(StringUtils.isEmpty(fileHash)); + // Non-existent file - uncreated with createNewFile() + file = new File("non-existent.tmp"); + Assert.assertNull(evidenceService.generateHash(file).getResult()); + Assert.assertNull(evidenceService.generateHash(StringUtils.EMPTY).getResult()); + Assert.assertFalse(StringUtils.isEmpty( + evidenceService.generateHash("10000").getResult().getHash())); + Assert.assertNull(evidenceService.generateHash(createCredentialArgs).getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/evidence/TestGetEvidence.java b/src/test/java/com/webank/weid/full/evidence/TestGetEvidence.java new file mode 100644 index 00000000..a3132569 --- /dev/null +++ b/src/test/java/com/webank/weid/full/evidence/TestGetEvidence.java @@ -0,0 +1,81 @@ + + +package com.webank.weid.full.evidence; + +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.fisco.bcos.sdk.utils.Numeric; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.base.EvidenceInfo; +import com.webank.weid.protocol.base.HashString; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DataToolUtils; +import com.webank.weid.util.DateUtils; + +/** + * TestGetEvidence v_wbpenghu. + */ +public class TestGetEvidence extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestGetEvidence.class); + + @Override + public synchronized void testInit() { + super.testInit(); + } + + /** + * case1: success. + */ + @Test + public void testGetEvidence_success() { + String hashStr = new CryptoSuite(0).hash(DateUtils.getNoMillisecondTimeStampString()); + HashString str = new HashString(Numeric.prependHexPrefix(hashStr)); + ResponseData evidence = evidenceService + .createEvidence(str, createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + Assert.assertTrue(!evidence.getResult().isEmpty()); + String evidenceAddress = evidence.getResult(); + ResponseData responseData = evidenceService + .getEvidence(evidenceAddress); + logger.info("testGetEvidenceCase1 result :" + responseData); + Assert.assertEquals(0, responseData.getErrorCode().intValue()); + Assert.assertEquals("success", responseData.getErrorMessage()); + EvidenceInfo evidenceInfo = responseData.getResult(); + for (int i = 1; i < evidenceInfo.getSignatures().size(); i++) { + Assert.assertEquals("0x0000000000000000000000000000000000000000", + evidenceInfo.getSigners().get(i)); + } + } + + /** + * case2: address is null. + */ + @Test + public void testGetEvidence_HashNull() { + + ResponseData responseData = evidenceService.getEvidence(null); + logger.info("testGetEvidenceCase2 result :" + responseData); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + responseData.getErrorCode().intValue()); + Assert.assertEquals("input parameter is illegal.", responseData.getErrorMessage()); + Assert.assertNull(responseData.getResult()); + } + + /** + * case3: address is "". + */ + @Test + public void testGetEvidence_HashIllegal() { + String evidenceAddress = "sdasfdcscwwewecas"; + ResponseData responseData = evidenceService.getEvidence(evidenceAddress); + logger.info("testGetEvidenceCase3 result :" + responseData); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), + responseData.getErrorCode().intValue()); + Assert.assertNull(responseData.getResult()); + } +} diff --git a/src/test/java/com/webank/weid/full/persistence/TestBaseTransportation.java b/src/test/java/com/webank/weid/full/persistence/TestBaseTransportation.java new file mode 100644 index 00000000..0d484169 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/TestBaseTransportation.java @@ -0,0 +1,222 @@ +package com.webank.weid.full.persistence; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.Challenge; +import com.webank.weid.protocol.base.ClaimPolicy; +import com.webank.weid.protocol.base.CredentialPojo; +import com.webank.weid.protocol.base.CredentialPojoList; +import com.webank.weid.protocol.base.PresentationE; +import com.webank.weid.protocol.base.PresentationPolicyE; +import com.webank.weid.protocol.base.WeIdAuthentication; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +public abstract class TestBaseTransportation extends TestBaseService { + + protected static PresentationE presentationE; + protected static PresentationPolicyE presentationPolicyE; + protected static Challenge challenge; + protected static List verifier = new ArrayList(); + protected static WeIdAuthentication weIdAuthentication; + + @Override + public synchronized void testInit() { + super.testInit(); + if (verifier.isEmpty()) { + verifier.add(createWeIdResult.getWeId()); + } + if (weIdAuthentication == null) { + weIdAuthentication = new WeIdAuthentication(); + weIdAuthentication.setWeId(createWeIdResult.getWeId()); + weIdAuthentication.setAuthenticationMethodId(createWeIdResult.getWeId() + "#key-0"); + weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); + weIdAuthentication.getWeIdPrivateKey().setPrivateKey( + createWeIdResult.getUserWeIdPrivateKey().getPrivateKey()); + } + } + + + protected PresentationE getPresentationE() { + ResponseData credentialPojoResponse = + credentialPojoService.createCredential(createCredentialPojoArgs); + if (credentialPojoResponse.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + List credentialList = new ArrayList<>(); + credentialList.add(credentialPojoResponse.getResult()); + + PresentationPolicyE presentationPolicyE = PresentationPolicyE.create("policy.json"); + if (presentationPolicyE == null) { + return null; + } + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy = policyMap.get(1000); + policyMap.remove(1000); + policyMap.put(createCredentialPojoArgs.getCptId(), cliamPolicy); + + this.presentationPolicyE = presentationPolicyE; + Challenge challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis()) + ); + this.challenge = challenge; + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + + if (response.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + return response.getResult(); + } + + protected PresentationE getPresentationE4MlCpt() { + ResponseData credentialPojoResponse = + credentialPojoService.createCredential(createCredentialPojoArgs1); + if (credentialPojoResponse.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + List credentialList = new ArrayList<>(); + credentialList.add(credentialPojoResponse.getResult()); + + PresentationPolicyE presentationPolicyE = PresentationPolicyE.create("test-policy.json"); + if (presentationPolicyE == null) { + return null; + } + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy = policyMap.get(1001); + policyMap.remove(1000); + policyMap.remove(1001); + policyMap.remove(1002); + policyMap.put(createCredentialPojoArgs1.getCptId(), cliamPolicy); + + this.presentationPolicyE = presentationPolicyE; + Challenge challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis()) + ); + this.challenge = challenge; + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + + if (response.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + return response.getResult(); + } + + protected PresentationE getPresentationE4MultiCpt() { + ResponseData credentialPojoResponse2 = + credentialPojoService.createCredential(createCredentialPojoArgs2); + + ResponseData credentialPojoResponse3 = + credentialPojoService.createCredential(createCredentialPojoArgs3); + + if (credentialPojoResponse2.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + + if (credentialPojoResponse3.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + + List credentialList = new ArrayList<>(); + credentialList.add(credentialPojoResponse2.getResult()); + credentialList.add(credentialPojoResponse3.getResult()); + + PresentationPolicyE presentationPolicyE = PresentationPolicyE.create("test-policy.json"); + if (presentationPolicyE == null) { + return null; + } + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy1000 = policyMap.get(1000); + ClaimPolicy cliamPolicy1001 = policyMap.get(1001); + + policyMap.remove(1000); + policyMap.remove(1001); + policyMap.remove(1002); + policyMap.put(createCredentialPojoArgs3.getCptId(), cliamPolicy1000); + policyMap.put(createCredentialPojoArgs2.getCptId(), cliamPolicy1001); + + this.presentationPolicyE = presentationPolicyE; + Challenge challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis()) + ); + this.challenge = challenge; + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + + if (response.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + return response.getResult(); + } + + protected PresentationE getPresentationE4SpecTplCpt() { + ResponseData credentialPojoResponse = + credentialPojoService.createCredential(createCredentialPojoArgs4); + if (credentialPojoResponse.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + List credentialList = new ArrayList<>(); + credentialList.add(credentialPojoResponse.getResult()); + + PresentationPolicyE presentationPolicyE = PresentationPolicyE + .create("test-spectpl-policy.json"); + if (presentationPolicyE == null) { + return null; + } + presentationPolicyE.setPolicyPublisherWeId(createWeIdResultWithSetAttr.getWeId()); + Map policyMap = presentationPolicyE.getPolicy(); + ClaimPolicy cliamPolicy1005 = policyMap.get(1005); + policyMap.remove(1005); + policyMap.put(createCredentialPojoArgs4.getCptId(), cliamPolicy1005); + + this.presentationPolicyE = presentationPolicyE; + Challenge challenge = Challenge.create( + createWeIdResultWithSetAttr.getWeId(), + String.valueOf(System.currentTimeMillis()) + ); + this.challenge = challenge; + ResponseData response = credentialPojoService.createPresentation( + credentialList, + presentationPolicyE, + challenge, + TestBaseUtil.buildWeIdAuthentication(createWeIdResultWithSetAttr) + ); + + if (response.getErrorCode() != ErrorCode.SUCCESS.getCode()) { + return null; + } + return response.getResult(); + } + + protected CredentialPojoList getCredentialPojoList(PresentationE presentation4MultiCpt) { + CredentialPojoList list = new CredentialPojoList(); + for (CredentialPojo credentialPojo : presentation4MultiCpt.getVerifiableCredential()) { + list.add(credentialPojo); + } + return list; + } +} diff --git a/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsAdd.java b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsAdd.java new file mode 100644 index 00000000..e17971b1 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsAdd.java @@ -0,0 +1,366 @@ + + +package com.webank.weid.full.persistence.testipfs; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +/** + * 因键值对存储方式与redis高度相似 所以直接复制的redis测试用例 + * + * @author 刘家辉 + * @date 2023/08/26 + */ +public class TestIpfsAdd extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestIpfsAdd.class); + + private static Persistence persistence = null; + + private static String idname = "test"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } else if (type.equals("ipfs")){ + persistenceType = PersistenceType.Ipfs; + } + persistence = PersistenceFactory.build(persistenceType); + } + + @Test + /** + * case:test add. + */ + public void testSave_success() { + + idname = "test" + Math.random(); + ResponseData res = persistence.add( + "domain.defaultInfo", + idname, + "dataAndData"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, idname); + Assert.assertEquals("dataAndData", data.getResult()); + } + + @Test + /** + * case:test batch add. + */ + public void testBatchAdd_success() { + persistence.delete("domain.defaultInfo", "12345"); + persistence.delete("domain.defaultInfo", "123456"); + HashMap map = new HashMap<>(); + map.put("12345", "12345"); + map.put("2313", "123456789"); + + ResponseData res = persistence.batchAdd( + "domain.defaultInfo", map); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertNotNull(res.getResult()); + + ResponseData data = persistence.get(null, "12345"); + Assert.assertEquals("12345", data.getResult()); + ResponseData data1 = persistence.get("", "2313"); + Assert.assertNotNull(data1.getResult()); + Assert.assertTrue(Arrays.equals( + "123456789".getBytes(StandardCharsets.ISO_8859_1), + data1.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + + @Test + /** + * case:insert data into a same database again. + */ + public void testSave_repeat() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + res.getErrorCode().intValue()); + + ResponseData res1 = persistence.add( + "domain.defaultInfo", + idname, + "data123456"); + Assert.assertEquals( + ErrorCode.PERSISTENCE_EXECUTE_FAILED.getCode(), + res1.getErrorCode().intValue()); + } + + @Test + /** + * case:domain is not spit by : . + */ + public void testSave_domainNoSpit() { + if (persistence.get(null, idname).getResult() != null) { + persistence.delete(null, idname); + } + + ResponseData res = persistence.add("datasource1", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain spit by : but the databases and table begin with space and end with space. + */ + //Expected :100903 + //Actual :100902 + public void testSave_domainContainSpace() { + ResponseData res = persistence.add( + " datasource1 : sdk_all_data ", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain is null. + */ + public void testSave_domainNull() { + + if (persistence.get(null, "123456") != null) { + persistence.delete(null, "123456"); + } + ResponseData res = persistence.add(null, + "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, "123456"); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:domain is blank. + */ + public void testSave_domainBlank() { + if (persistence.get("", idname) != null) { + persistence.delete("", idname); + } + ResponseData res = persistence.add("", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:database is zh. + */ + + //Expected :0 + //Actual :100902 + public void testSave_domainContainZh() { + String id = idname + System.currentTimeMillis(); + ResponseData res = persistence.add("datasource1:夏石龙", + id, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain has special character. + */ + public void testSave_domainContainSpecialChar() { + + ResponseData res = persistence + .add("datasource1:mnj><:??li", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:id is zh. + */ + public void testSave_idZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("datasource1:夏石龙", idname); + idname = "test" + Math.random() + "中国"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:id contains special char. + */ + public void testSave_idContainSpecialChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "0x23!@#¥%……&*-+"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:id contains special char. + */ + public void testSave_idContainKeyWord() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:data contains zh. + */ + public void testSave_dataZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "中国我爱你"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertTrue(Arrays.equals( + "中国我爱你".getBytes(StandardCharsets.ISO_8859_1), + data.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + @Test + /** + * case:data contains special char. + */ + public void testSave_dataContainSpeciaChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "12!@##$$%^^&*()-+?>we"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:data contains special char. + */ + public void testSave_dataIsTooLong() { + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (1000 % 127); + } + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, String.valueOf(chars)); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsDelete.java b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsDelete.java new file mode 100644 index 00000000..9203e76d --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsDelete.java @@ -0,0 +1,101 @@ + + +package com.webank.weid.full.persistence.testipfs; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestIpfsDelete extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestIpfsDelete.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } else if (type.equals("ipfs")){ + persistenceType = PersistenceType.Ipfs; + } + persistence = PersistenceFactory.build(persistenceType); + save_data(); + } + + @Test + /** + * case:test add. + */ + public void save_data() { + + ResponseData res = persistence.delete(domain, id); + LogUtil.info(logger, "persistence", res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + ResponseData result = persistence.add(domain, id, data); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), result.getErrorCode().intValue()); + Assert.assertEquals(1, result.getResult().intValue()); + } + + @Test + /** + * case:id is not exist. + */ + public void testDelete_idNotExist() { + + ResponseData res = persistence.delete(domain, "id_is_not_exist"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(0, res.getResult().intValue()); + } + + @Test + /** + * case:test id is null. + */ + public void testDelete_idNull() { + + ResponseData res = persistence.delete(domain, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test id is blank. + */ + public void testDelete_idBlank() { + + ResponseData res = persistence.delete(domain, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsGet.java b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsGet.java new file mode 100644 index 00000000..e617aa05 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsGet.java @@ -0,0 +1,133 @@ + + +package com.webank.weid.full.persistence.testipfs; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestIpfsGet extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestIpfsGet.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } else if (type.equals("ipfs")){ + persistenceType = PersistenceType.Ipfs; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData response = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(1, response.getResult().intValue()); + } + + @Test + /** + * case:test get. + */ + public void testGet_success() { + + ResponseData res = persistence.get( + domain, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_databaseNotExist() { + + ResponseData res = persistence.get("sourcedata9999:sdk_all_data", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_domainIsNull() { + + ResponseData res = persistence.get(null, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_domainIsBlank() { + + ResponseData res = persistence.get("", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test table is not exist. + */ + public void testGet_TableNotExist() { + String dataSource = domain.split(":")[0]; + ResponseData res = persistence.get( + dataSource + ":table_not_exist", "123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test id is not exist. + */ + //expected null, but was:<> + public void testGet_idNotExist() { + + ResponseData res = persistence.get(domain, id + Math.random()); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals("", res.getResult()); + } + + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsUpdate.java b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsUpdate.java new file mode 100644 index 00000000..9a5861d7 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testipfs/TestIpfsUpdate.java @@ -0,0 +1,152 @@ + + +package com.webank.weid.full.persistence.testipfs; + +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.common.LogUtil; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestIpfsUpdate extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestIpfsUpdate.class); + + private static String domain = "domain.defaultInfo"; + + private static String id = "123456"; + + private static final String data = "data123456"; + + private Persistence persistence = null; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } else if (type.equals("ipfs")){ + persistenceType = PersistenceType.Ipfs; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData ret = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), ret.getErrorCode().intValue()); + } + + @Test + /** + * case:test update. + */ + public void testUpdate_success() { + + ResponseData res = persistence.update( + domain, id, data + " update"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(data + " update", result.getResult()); + } + + @Test + /** + * case:test update domain is null. + */ + public void testUpdate_domainNull() { + String afterData = data + Math.random(); + ResponseData res = persistence.update(null, id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + @Test + /** + * case:domain is blank. + */ + public void testUpdate_domainBlank() { + String afterData = data + Math.random(); + ResponseData res = persistence.update("", id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + @Test + /** + * case:test update table is not exist. + */ + public void testUpdate_idNull() { + + ResponseData res = persistence.update(domain, null, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test update id is blank. + */ + public void testUpdate_idBlank() { + + ResponseData res = persistence.update( + "datasource9999:sdk_all_data", "", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test update data is null. + */ + public void testUpdate_dataNull() { + + ResponseData res = persistence.update( + domain, id, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(1, res.getResult().intValue()); + } + + @Test + /** + * case:test update data is blank. + */ + public void testUpdate_dataBlank() { + + ResponseData res = persistence.update( + domain, id, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals("", result.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlAdd.java b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlAdd.java new file mode 100644 index 00000000..cb41e4f2 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlAdd.java @@ -0,0 +1,366 @@ + + +package com.webank.weid.full.persistence.testmysql; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +public class TestMysqlAdd extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestMysqlAdd.class); + + private static Persistence persistence = null; + + private static String idname = "test"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + } + + + /** + * case:test add. + */ + @Test + public void testSave_success() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence.add( + "domain.defaultInfo", + idname, + "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, idname); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:test batch add. + */ + @Test + public void testBatchAdd_success() { + persistence.delete("domain.defaultInfo", "1111aa"); + persistence.delete("domain.defaultInfo", "1222bb"); + HashMap map = new HashMap<>(); + map.put("1111aa", "12345"); + map.put("1222bb", "123456789"); + ResponseData res = persistence.batchAdd("domain.defaultInfo", map); + LogUtil.info(logger, "persistence", res); + System.out.println(res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertNotNull(res.getResult()); + + ResponseData data = persistence.get(null, "1111aa"); + Assert.assertEquals("12345", data.getResult()); + ResponseData data1 = persistence.get("", "1222bb"); + Assert.assertNotNull(data1.getResult()); + Assert.assertTrue(Arrays.equals( + "123456789".getBytes(StandardCharsets.ISO_8859_1), + data1.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + + /** + * case:insert data into a same database again. + */ + @Test + public void testAdd_repeat() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData res1 = persistence + .add("domain.defaultInfo", idname, "data123456"); + Assert.assertEquals(ErrorCode.PERSISTENCE_EXECUTE_FAILED.getCode(), + res1.getErrorCode().intValue()); + } + + + /** + * case:domain is not spit by : . + */ + @Test + public void testAdd_domainNoSpit() { + if (persistence.get(null, idname).getResult() != null) { + persistence.delete(null, idname); + } + + ResponseData res = persistence.add("datasource1", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:domain spit by : but the databases and table begin with space and end with space. + */ + @Test + public void testAdd_domainContainSpace() { + ResponseData res = persistence.add( + " datasource1 : sdk_all_data ", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:domain is null. + */ + @Test + public void testAdd_domainNull() { + + if (persistence.get(null, "123456") != null) { + persistence.delete(null, "123456"); + } + ResponseData res = persistence.add(null, + "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, "123456"); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:domain is blank. + */ + @Test + public void testAdd_domainBlank() { + if (persistence.get("", idname) != null) { + persistence.delete("", idname); + } + ResponseData res = persistence.add("", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:database is zh. + */ + @Test + public void testAdd_domainContainZh() { + String id = idname + System.currentTimeMillis(); + ResponseData res = persistence.add("datasource1:夏石龙", + id, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + + } + + + /** + * case:domain hasspecial character. + */ + @Test + public void testAdd_domainContainSpecialChar() { + + ResponseData res = persistence + .add("datasource1:mnj><:??li", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:id is zh. + */ + @Test + public void testAdd_idZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("datasource1:夏石龙", idname); + idname = "test" + Math.random() + "中国"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:id contains special char. + */ + @Test + public void testAdd_idContainSpecialChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "0x23!@#¥%……&*-+"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:id contains special char. + */ + @Test + public void testAdd_idContainKeyWord() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + + /** + * case:data contains zh. + */ + @Test + public void testAdd_dataZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "中国我爱你"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertTrue(Arrays.equals( + "中国我爱你".getBytes(StandardCharsets.ISO_8859_1), + data.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + + /** + * case:data contains special char. + */ + @Test + public void testAdd_dataContainSpeciaChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "12!@##$$%^^&*()-+?>we"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:data contains special char. + */ + @Test + public void testAdd_dataIsTooLong() { + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (1000 % 127); + } + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, String.valueOf(chars)); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlDelete.java b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlDelete.java new file mode 100644 index 00000000..1edcfa86 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlDelete.java @@ -0,0 +1,169 @@ + + +package com.webank.weid.full.persistence.testmysql; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestMysqlDelete extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestMysqlDelete.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + save_data(); + } + + + /** + * case:test add. + */ + public void save_data() { + + ResponseData res = persistence.delete(domain, id); + LogUtil.info(logger, "persistence", res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.add(domain, id, data); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), result.getErrorCode().intValue()); + Assert.assertEquals(1, result.getResult().intValue()); + } + + + /** + * case:test delete database not exist. + */ + public void testDelete_databaseNotExist() { + String table = domain.split("\\.")[1]; + + ResponseData res = persistence.delete( + "9999999." + table, "123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test database is null. + */ + public void testDelete_databaseNull() { + String table = domain.split("\\.")[1]; + ResponseData res = persistence.delete( + "null." + table, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test database is blank. + */ + public void testDelete_databaseBlank() { + + String table = domain.split("\\.")[1]; + ResponseData res = persistence.delete("." + table, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test table is not exist. + */ + public void testDelete_tableNotExist() { + String dataSource = domain.split("\\.")[0]; + ResponseData res = persistence.delete( + dataSource + ".table_not_exist", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test table is null. + */ + public void testDelete_tableNull() { + String dataSource = domain.split("\\.")[0]; + ResponseData res = persistence.delete(dataSource + ".", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:id is not exist. + */ + public void testDelete_idNotExist() { + + ResponseData res = persistence.delete(domain, "id_is_not_exist"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(0, res.getResult().intValue()); + } + + + /** + * case:test id is null. + */ + public void testDelete_idNull() { + + ResponseData res = persistence.delete(domain, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test id is blank. + */ + public void testDelete_idBlank() { + + ResponseData res = persistence.delete(domain, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlGet.java b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlGet.java new file mode 100644 index 00000000..5f1ef2b2 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlGet.java @@ -0,0 +1,126 @@ + + +package com.webank.weid.full.persistence.testmysql; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestMysqlGet extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestMysqlGet.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData response = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(1, response.getResult().intValue()); + } + + /** + * case:test get. + */ + public void testGet_success() { + + ResponseData res = persistence.get( + domain, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + + /** + * case:test database is not exist. + */ + public void testGet_databaseNotExist() { + + ResponseData res = persistence.get("sourcedata9999:sdk_all_data", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test database is not exist. + */ + public void testGet_domainIsNull() { + + ResponseData res = persistence.get(null, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + + /** + * case:test database is not exist. + */ + public void testGet_domainIsBlank() { + + ResponseData res = persistence.get("", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + + /** + * case:test table is not exist. + */ + public void testGet_TableNotExist() { + String dataSource = domain.split(":")[0]; + ResponseData res = persistence.get( + dataSource + ":table_not_exist", "123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test id is not exist. + */ + public void testGet_idNotExist() { + + ResponseData res = persistence.get(domain, id + Math.random()); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals("", res.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlUpdate.java b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlUpdate.java new file mode 100644 index 00000000..3a8c3d70 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testmysql/TestMysqlUpdate.java @@ -0,0 +1,245 @@ + + +package com.webank.weid.full.persistence.testmysql; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestMysqlUpdate extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestMysqlUpdate.class); + + private static String domain = "domain.defaultInfo"; + + private static String id = "123456"; + + private static final String data = "data123456"; + + private Persistence persistence = null; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData ret = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), ret.getErrorCode().intValue()); + } + + + /** + * case:test update. + */ + public void testUpdate_success() { + + ResponseData res = persistence.update( + domain, id, data + " update"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(data + " update", result.getResult()); + } + + + /** + * case:test update domain is null. + */ + public void testUpdate_domainNull() { + String afterData = data + Math.random(); + ResponseData res = persistence.update(null, id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + + /** + * case:domain is blank. + */ + public void testUpdate_domainBlank() { + String afterData = data + Math.random(); + ResponseData res = persistence.update("", id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + + /** + * case:test update. + */ + public void testUpdate_databaseNotExist() { + + ResponseData res = persistence.update( + "9999:sdk_all_data", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test update database is null. + */ + public void testUpdate_databaseNull() { + + ResponseData res = persistence.update( + "null:sdk_all_data", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test update database is blank. + */ + public void testUpdate_databaseBlank() { + + ResponseData res = persistence.update(":sdk_all_data", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test update table is not exist. + */ + public void testUpdate_tableNotExist() { + + ResponseData res = persistence.update( + "datasource1:sdk_all_data_not_exist", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test update table is null. + */ + public void testUpdate_tableNull() { + + ResponseData res = persistence.update("datasource1:null", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test update table is blank. + */ + public void testUpdate_tableBlank() { + + ResponseData res = persistence.update("datasource1:", id, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + + /** + * case:test update id is not exist. + */ + public void testUpdate_idNotExist() { + + ResponseData res = persistence.update( + domain, id + "not exist", data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(0, res.getResult().intValue()); + } + + + /** + * case:test update table is not exist. + */ + public void testUpdate_idNull() { + + ResponseData res = persistence.update(domain, null, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test update id is blank. + */ + public void testUpdate_idBlank() { + + ResponseData res = persistence.update( + "datasource9999:sdk_all_data", "", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + + /** + * case:test update data is null. + */ + public void testUpdate_dataNull() { + + ResponseData res = persistence.update( + domain, id, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(1, res.getResult().intValue()); + } + + + /** + * case:test update data is blank. + */ + public void testUpdate_dataBlank() { + + ResponseData res = persistence.update( + domain, id, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals("", result.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisAdd.java b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisAdd.java new file mode 100644 index 00000000..43aac8e0 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisAdd.java @@ -0,0 +1,359 @@ + + +package com.webank.weid.full.persistence.testredis; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +import com.webank.weid.full.persistence.TestBaseTransportation; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; + +public class TestRedisAdd extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestRedisAdd.class); + + private static Persistence persistence = null; + + private static String idname = "test"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + } + + @Test + /** + * case:test add. + */ + public void testSave_success() { + + idname = "test" + Math.random(); + ResponseData res = persistence.add( + "domain.defaultInfo", + idname, + "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:test batch add. + */ + public void testBatchAdd_success() { + persistence.delete("domain.defaultInfo", "12345"); + persistence.delete("domain.defaultInfo", "123456"); + HashMap map = new HashMap<>(); + map.put("12345", "12345"); + map.put("2313", "123456789"); + + ResponseData res = persistence.batchAdd( + "domain.defaultInfo", map); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertNotNull(res.getResult()); + + ResponseData data = persistence.get(null, "12345"); + Assert.assertEquals("12345", data.getResult()); + ResponseData data1 = persistence.get("", "2313"); + Assert.assertNotNull(data1.getResult()); + Assert.assertTrue(Arrays.equals( + "123456789".getBytes(StandardCharsets.ISO_8859_1), + data1.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + + @Test + /** + * case:insert data into a same database again. + */ + public void testSave_repeat() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.SUCCESS.getCode(), + res.getErrorCode().intValue()); + + ResponseData res1 = persistence.add( + "domain.defaultInfo", + idname, + "data123456"); + Assert.assertEquals( + ErrorCode.PERSISTENCE_EXECUTE_FAILED.getCode(), + res1.getErrorCode().intValue()); + } + + @Test + /** + * case:domain is not spit by : . + */ + public void testSave_domainNoSpit() { + if (persistence.get(null, idname).getResult() != null) { + persistence.delete(null, idname); + } + + ResponseData res = persistence.add("datasource1", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain spit by : but the databases and table begin with space and end with space. + */ + //Expected :100903 + //Actual :100902 + public void testSave_domainContainSpace() { + ResponseData res = persistence.add( + " datasource1 : sdk_all_data ", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain is null. + */ + public void testSave_domainNull() { + + if (persistence.get(null, "123456") != null) { + persistence.delete(null, "123456"); + } + ResponseData res = persistence.add(null, + "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get(null, "123456"); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:domain is blank. + */ + public void testSave_domainBlank() { + if (persistence.get("", idname) != null) { + persistence.delete("", idname); + } + ResponseData res = persistence.add("", + idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:database is zh. + */ + + //Expected :0 + //Actual :100902 + public void testSave_domainContainZh() { + String id = idname + System.currentTimeMillis(); + ResponseData res = persistence.add("datasource1:夏石龙", + id, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:domain has special character. + */ + public void testSave_domainContainSpecialChar() { + + ResponseData res = persistence + .add("datasource1:mnj><:??li", "123456", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:id is zh. + */ + public void testSave_idZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("datasource1:夏石龙", idname); + idname = "test" + Math.random() + "中国"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:id contains special char. + */ + public void testSave_idContainSpecialChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "0x23!@#¥%……&*-+"; + } + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:id contains special char. + */ + public void testSave_idContainKeyWord() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random() + "select"; + } + + ResponseData res = persistence + .add("domain.defaultInfo", idname, "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertEquals("data123456", data.getResult()); + } + + @Test + /** + * case:data contains zh. + */ + public void testSave_dataZh() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "中国我爱你"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData data = persistence.get("domain.defaultInfo", idname); + Assert.assertTrue(Arrays.equals( + "中国我爱你".getBytes(StandardCharsets.ISO_8859_1), + data.getResult().getBytes(StandardCharsets.ISO_8859_1))); + } + + @Test + /** + * case:data contains special char. + */ + public void testSave_dataContainSpeciaChar() { + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, "12!@##$$%^^&*()-+?>we"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:data contains special char. + */ + public void testSave_dataIsTooLong() { + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (1000 % 127); + } + + ResponseData response = new ResponseData<>(); + response.setResult("test"); + while (StringUtils.isNotBlank(response.getResult())) { + response = persistence.get("domain.defaultInfo", idname); + idname = "test" + Math.random(); + } + + ResponseData res = persistence.add( + "domain.defaultInfo", idname, String.valueOf(chars)); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisDelete.java b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisDelete.java new file mode 100644 index 00000000..cdaecc40 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisDelete.java @@ -0,0 +1,100 @@ + + +package com.webank.weid.full.persistence.testredis; + +import com.webank.weid.full.persistence.TestBaseTransportation; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; + +public class TestRedisDelete extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestRedisDelete.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + save_data(); + } + + @Test + /** + * case:test add. + */ + public void save_data() { + + ResponseData res = persistence.delete(domain, id); + LogUtil.info(logger, "persistence", res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + ResponseData result = persistence.add(domain, id, data); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), result.getErrorCode().intValue()); + Assert.assertEquals(1, result.getResult().intValue()); + } + + @Test + /** + * case:id is not exist. + */ + public void testDelete_idNotExist() { + + ResponseData res = persistence.delete(domain, "id_is_not_exist"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(0, res.getResult().intValue()); + } + + @Test + /** + * case:test id is null. + */ + public void testDelete_idNull() { + + ResponseData res = persistence.delete(domain, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test id is blank. + */ + public void testDelete_idBlank() { + + ResponseData res = persistence.delete(domain, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisGet.java b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisGet.java new file mode 100644 index 00000000..0ad4027a --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisGet.java @@ -0,0 +1,131 @@ + + +package com.webank.weid.full.persistence.testredis; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestRedisGet extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestRedisGet.class); + + private Persistence persistence = null; + + private static final String domain = "domain.defaultInfo"; + + private static final String id = "123456"; + + private static final String data = "data123456"; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData response = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(1, response.getResult().intValue()); + } + + @Test + /** + * case:test get. + */ + public void testGet_success() { + + ResponseData res = persistence.get( + domain, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_databaseNotExist() { + + ResponseData res = persistence.get("sourcedata9999:sdk_all_data", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), res.getErrorCode().intValue()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_domainIsNull() { + + ResponseData res = persistence.get(null, id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test database is not exist. + */ + public void testGet_domainIsBlank() { + + ResponseData res = persistence.get("", id); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(data, res.getResult()); + } + + @Test + /** + * case:test table is not exist. + */ + public void testGet_TableNotExist() { + String dataSource = domain.split(":")[0]; + ResponseData res = persistence.get( + dataSource + ":table_not_exist", "123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals( + ErrorCode.PRESISTENCE_DOMAIN_ILLEGAL.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test id is not exist. + */ + //expected null, but was:<> + public void testGet_idNotExist() { + + ResponseData res = persistence.get(domain, id + Math.random()); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals("", res.getResult()); + } + + +} diff --git a/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisUpdate.java b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisUpdate.java new file mode 100644 index 00000000..6c3c0678 --- /dev/null +++ b/src/test/java/com/webank/weid/full/persistence/testredis/TestRedisUpdate.java @@ -0,0 +1,150 @@ + + +package com.webank.weid.full.persistence.testredis; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.persistence.TestBaseTransportation; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.suite.persistence.Persistence; +import com.webank.weid.suite.persistence.PersistenceFactory; +import com.webank.weid.suite.persistence.PersistenceType; +import com.webank.weid.util.PropertyUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestRedisUpdate extends TestBaseTransportation { + + private static final Logger logger = LoggerFactory.getLogger(TestRedisUpdate.class); + + private static String domain = "domain.defaultInfo"; + + private static String id = "123456"; + + private static final String data = "data123456"; + + private Persistence persistence = null; + + private static PersistenceType persistenceType = null; + + @Override + public synchronized void testInit() { + + String type = PropertyUtils.getProperty("persistence_type"); + if (type.equals("mysql")) { + persistenceType = PersistenceType.Mysql; + } else if (type.equals("redis")) { + persistenceType = PersistenceType.Redis; + } + persistence = PersistenceFactory.build(persistenceType); + persistence.delete(domain, id); + ResponseData ret = persistence.add(domain, id, data); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), ret.getErrorCode().intValue()); + } + + @Test + /** + * case:test update. + */ + public void testUpdate_success() { + + ResponseData res = persistence.update( + domain, id, data + " update"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(data + " update", result.getResult()); + } + + @Test + /** + * case:test update domain is null. + */ + public void testUpdate_domainNull() { + String afterData = data + Math.random(); + ResponseData res = persistence.update(null, id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + @Test + /** + * case:domain is blank. + */ + public void testUpdate_domainBlank() { + String afterData = data + Math.random(); + ResponseData res = persistence.update("", id, afterData); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals(afterData, result.getResult()); + } + + @Test + /** + * case:test update table is not exist. + */ + public void testUpdate_idNull() { + + ResponseData res = persistence.update(domain, null, data); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test update id is blank. + */ + public void testUpdate_idBlank() { + + ResponseData res = persistence.update( + "datasource9999:sdk_all_data", "", "data123456"); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.PRESISTENCE_DATA_KEY_INVALID.getCode(), + res.getErrorCode().intValue()); + } + + @Test + /** + * case:test update data is null. + */ + public void testUpdate_dataNull() { + + ResponseData res = persistence.update( + domain, id, null); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + Assert.assertEquals(1, res.getResult().intValue()); + } + + @Test + /** + * case:test update data is blank. + */ + public void testUpdate_dataBlank() { + + ResponseData res = persistence.update( + domain, id, ""); + LogUtil.info(logger, "persistence", res); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData result = persistence.get(domain, id); + Assert.assertEquals("", result.getResult()); + } + +} diff --git a/src/test/java/com/webank/weid/full/weid/TestCreateWeId1.java b/src/test/java/com/webank/weid/full/weid/TestCreateWeId1.java index 319e2c61..af7d6caf 100644 --- a/src/test/java/com/webank/weid/full/weid/TestCreateWeId1.java +++ b/src/test/java/com/webank/weid/full/weid/TestCreateWeId1.java @@ -1,241 +1,92 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; + +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.CreateWeIdArgs; import mockit.Mock; import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * non parametric createWeId method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestCreateWeId1 extends TestBaseServcie { +public class TestCreateWeId1 extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestCreateWeId1.class); /** * case: create WeId success. - * - * @throws Exception may be throw Exception */ @Test - public void testCreateWeIdCase1() throws Exception { + public void testCreateWeId_createSuccess() { ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } /** - * case: Simulation throws an TimeoutException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testCreateWeIdCase2() throws Exception { - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } - - /** - * case: Simulation throws an InterruptedException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case:run CreateWeId twice Will create two different WeId. */ @Test - public void testCreateWeIdCase3() throws Exception { - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testCreateWeId_doubleCreateSuccess() { ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); + LogUtil.info(logger, "createWeId", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); + ResponseData response1 = weIdService.createWeId(); + LogUtil.info(logger, "createWeId", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertNotNull(response1.getResult()); + Assert.assertNotEquals(response.getResult().getWeId(), response1.getResult().getWeId()); } /** - * case: Simulation returns null when invoking the getWeIdAttributeChangedEvents - * method. - * - * @throws Exception may be throw Exception + * case: create WeId success. */ @Test - public void testCreateWeIdCase4() throws Exception { - - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - return null; - } - }; - - ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + public void testCreateWeIdByPublicKey_createSuccess() { + CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(createWeIdArgs.getPublicKey()); + ResponseData response = weIdService.createWeIdByPublicKey(weIdPublicKey, createWeIdArgs.getWeIdPrivateKey()); + LogUtil.info(logger, "createWeId", response); - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); } /** - * case: Simulation throws an NullPointerException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case: create WeId success, public key not match with private key. */ @Test - public void testCreateWeIdCase5() throws Exception { - - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - throw new NullPointerException(); - } - }; - - ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + public void testCreateWeIdByPublicKey_createSuccess2() { + CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); + WeIdPublicKey weIdPublicKey = new WeIdPublicKey(); + weIdPublicKey.setPublicKey(createWeIdArgs.getPublicKey()); + ResponseData response = weIdService.createWeIdByPublicKey(weIdPublicKey, createWeIdNew.getUserWeIdPrivateKey()); + LogUtil.info(logger, "createWeId", response); - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertNotNull(response.getResult()); } - /** - * case: Simulation throws an exception when calling the createEcKeyPair - * method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testCreateWeIdCase6() throws Exception { - - MockUp mockTest = new MockUp() { - @Mock - public ECKeyPair createEcKeyPair() - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, - NoSuchProviderException { - throw new NoSuchProviderException(); - } - }; - - ResponseData response = weIdService.createWeId(); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.WEID_KEYPAIR_CREATE_FAILED.getCode(), - response.getErrorCode().intValue()); - Assert.assertNull(response.getResult()); - } } diff --git a/src/test/java/com/webank/weid/full/weid/TestCreateWeId2.java b/src/test/java/com/webank/weid/full/weid/TestCreateWeId2.java index 0bd7c1a5..6d1e9a58 100644 --- a/src/test/java/com/webank/weid/full/weid/TestCreateWeId2.java +++ b/src/test/java/com/webank/weid/full/weid/TestCreateWeId2.java @@ -1,105 +1,160 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.exception.PrivateKeyIllegalException; -import com.webank.weid.full.TestBaseServcie; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdPrivateKey; import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.service.BaseService; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; +import com.webank.weid.blockchain.protocol.response.ResponseData; import org.apache.commons.lang3.StringUtils; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.bcos.web3j.tx.Contract; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * a parametric createWeId method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestCreateWeId2 extends TestBaseServcie { +public class TestCreateWeId2 extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestCreateWeId2.class); /** - * case: create success. - * - * @throws Exception may be throw Exception + * case: create weid with param success. */ @Test - public void testCreateWeIdCase1() throws Exception { - + public void testCreateWeId_paramSuccess() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); - + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); } /** - * case: createWeIdArgs is null. - * - * @throws Exception may be throw Exception + * case: when createWeIdArgs is null,then return ILLEGAL_INPUT. */ @Test - public void testCreateWeIdCase2() throws Exception { - - ResponseData response = weIdService.createWeId(null); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + public void testCreateWeId_weIdArgsIsNull() { + CreateWeIdArgs createWeIdArgs = null; + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); } + /** + * case: when public key is wrong,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyIsW() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey("019WEASDFE"); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + + /** + * case: when publickey is digtal,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyIsDigital() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey("1234567493064"); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + + /** + * case: when public key is start with ox,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyIsHex() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey("0x11a3c3123"); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + + /** + * case: when public key contain special char,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyContainSpecialChar() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey("-~!@#$%^&."); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + + /** + * case: when public key contain zh,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyContainZh() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + createWeIdArgs.setPublicKey("我爱你中国"); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + + /** + * case: when public key is too long ,then return WEID_PRIVATEKEY_INVALID. + */ + @Test + public void testCreateWeId_publicKeyIsTooLong() { + CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) i; + } + createWeIdArgs.setPublicKey(chars.toString()); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + response.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + } + /** * case: publicKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testCreateWeIdCase3() throws Exception { + public void testCreateWeId_publicKeyIsNull() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); createWeIdArgs.setPublicKey(null); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_INVALID.getCode(), response.getErrorCode().intValue()); @@ -108,18 +163,15 @@ public void testCreateWeIdCase3() throws Exception { /** * case: publicKey is Non integer string. - * - * @throws Exception may be throw Exception */ @Test - public void testCreateWeIdCase4() throws Exception { + public void testCreateWeId_keyNotMatch() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); createWeIdArgs.setPublicKey("abc"); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED.getCode(), response.getErrorCode().intValue()); @@ -127,39 +179,53 @@ public void testCreateWeIdCase4() throws Exception { } /** - * case: weIdPrivateKey is null. - * - * @throws Exception may be throw Exception + * case: when publicKey has been used,return WEID_ALREADY_EXIST. */ @Test - public void testCreateWeIdCase5() throws Exception { - + public void testCreateWeId_pubKeyUsed() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - createWeIdArgs.setWeIdPrivateKey(null); + String publicKey = createWeIdArgs.getPublicKey(); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + createWeIdArgs.setPublicKey(publicKey); + ResponseData response1 = weIdService.createWeId(createWeIdArgs); + Assert.assertEquals(ErrorCode.WEID_ALREADY_EXIST.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response1.getResult()); + } + /** + * case: when private key has been used,return WEID_ALREADY_EXIST. + */ + @Test + public void testCreateWeId_priKeyUsed() { + CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + + CreateWeIdArgs createWeIdArgs1 = TestBaseUtil.buildCreateWeIdArgs(); + createWeIdArgs1.setWeIdPrivateKey(createWeIdArgs.getWeIdPrivateKey()); + + ResponseData response1 = weIdService.createWeId(createWeIdArgs1); + Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED.getCode(), + response1.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, response1.getResult()); } /** - * case: privateKey is null. - * - * @throws Exception may be throw Exception + * case: weIdPrivateKey is null. */ @Test - public void testCreateWeIdCase6() throws Exception { + public void testCreateWeId_privateKeyIsNull() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - createWeIdArgs.getWeIdPrivateKey().setPrivateKey(null); + createWeIdArgs.setWeIdPrivateKey(null); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); @@ -167,40 +233,35 @@ public void testCreateWeIdCase6() throws Exception { } /** - * case: privateKey is invalid. - * - * @throws Exception may be throw Exception + * case: weIdPrivateKey contains interer and string. */ @Test - public void testCreateWeIdCase7() throws Exception { + public void testCreateWeId_privateKeyContainIntAndChar() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - createWeIdArgs.getWeIdPrivateKey().setPrivateKey("xxxxxxxxxxxx"); - + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("019WEASDFE"); + createWeIdArgs.setWeIdPrivateKey(weIdPrivateKey); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); - Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); } /** - * case: privateKey and publicKey misMatch. - * - * @throws Exception may be throw Exception + * case: weIdPrivateKey contains interer and string. */ @Test - public void testCreateWeIdCase8() throws Exception { + public void testCreateWeId_privateKeyIsInteger() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - String[] pk = TestBaseUtil.createEcKeyPair(); - createWeIdArgs.getWeIdPrivateKey().setPrivateKey(pk[1]); - + WeIdPrivateKey weIdPrivateKey = new WeIdPrivateKey(); + weIdPrivateKey.setPrivateKey("1234567493064"); + createWeIdArgs.setWeIdPrivateKey(weIdPrivateKey); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED.getCode(), response.getErrorCode().intValue()); @@ -208,199 +269,120 @@ public void testCreateWeIdCase8() throws Exception { } /** - * case: Simulation returns null when invoking the getWeIdAttributeChangedEvents - * method. - * - * @throws Exception may be throw Exception + * case: privateKey is null. */ @Test - public void testCreateWeIdCase9() throws Exception { - - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - return null; - } - }; + public void testCreateWeId_setPrivateKeyNull() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + createWeIdArgs.getWeIdPrivateKey().setPrivateKey(null); - mockTest.tearDown(); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); } /** - * case: Simulation throws an InterruptedException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case: privateKey is invalid. */ @Test - public void testCreateWeIdCase10() throws Exception { - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testCreateWeId_privateKeyIsInvalid() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + createWeIdArgs.getWeIdPrivateKey().setPrivateKey("xxxxxxxxxxxx"); - mockTest.tearDown(); - mockFuture.tearDown(); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); } /** - * case: Simulation throws an TimeoutException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case: privateKey has been used. */ @Test - public void testCreateWeIdCase11() throws Exception { - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testCreateWeId_privateKeyIsExist() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); + WeIdPrivateKey weIdPrivateKey = createWeIdArgs.getWeIdPrivateKey(); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(StringUtils.EMPTY, response.getResult()); + + createWeIdArgs.setWeIdPrivateKey(weIdPrivateKey); + ResponseData response1 = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response1); + Assert.assertEquals(ErrorCode.WEID_ALREADY_EXIST.getCode(), + response1.getErrorCode().intValue()); } /** - * case: Simulation throws an NullPointerException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case: privateKey and publicKey misMatch. */ @Test - public void testCreateWeIdCase12() throws Exception { - - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - throw new NullPointerException(); - } - }; + public void testCreateWeIdCase8() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + createWeIdArgs.getWeIdPrivateKey().setPrivateKey(passwordKey.getPrivateKey()); - mockTest.tearDown(); + ResponseData response = weIdService.createWeId(createWeIdArgs); + LogUtil.info(logger, "createWeId", response); - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_PUBLICKEY_AND_PRIVATEKEY_NOT_MATCHED.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); } + /** - * case: Simulation throws an PrivateKeyIllegalException when calling the - * reloadContract method. - * - * @throws Exception may be throw Exception + * case: Simulation throws an PrivateKeyIllegalException when calling the reloadContract + * method. */ - @Test - public void testCreateWeIdCase13() throws Exception { + /*@Test + public void testCreateWeIdCase13() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); - MockUp mockTest = new MockUp() { + new MockUp() { @Mock - public Contract reloadContract(String contractAddress, String privateKey, Class cls) + public T reloadContract(String contractAddress, String privateKey, Class cls) throws PrivateKeyIllegalException { + throw new PrivateKeyIllegalException(); } }; ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); - - mockTest.tearDown(); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, response.getResult()); - } + }*/ /** * case: create again. - * - * @throws Exception may be throw Exception */ @Test - public void testCreateWeIdCase14() throws Exception { + public void testCreateWeId_repeatCreate() { CreateWeIdArgs createWeIdArgs = TestBaseUtil.buildCreateWeIdArgs(); ResponseData response = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response); + LogUtil.info(logger, "createWeId", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertNotNull(response.getResult()); ResponseData response1 = weIdService.createWeId(createWeIdArgs); - System.out.println("\ncreateWeId result:"); - BeanUtil.print(response1); + LogUtil.info(logger, "createWeId", response1); Assert.assertEquals(ErrorCode.WEID_ALREADY_EXIST.getCode(), response1.getErrorCode().intValue()); diff --git a/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocument.java b/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocument.java index 97842a65..a3beeef2 100644 --- a/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocument.java +++ b/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocument.java @@ -1,137 +1,139 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.full.TestBaseServcie; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; import com.webank.weid.full.TestBaseUtil; import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.response.ResponseData; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.generated.Uint256; +import com.webank.weid.protocol.base.WeIdPublicKey; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.protocol.response.WeIdListResult; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; /** * getWeIdDocument method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestGetWeIdDocument extends TestBaseServcie { +public class TestGetWeIdDocument extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestGetWeIdDocument.class); + + + private static CreateWeIdDataResult createWeIdForGetDoc = null; + + @Override + public synchronized void testInit() { + super.testInit(); + if (createWeIdForGetDoc == null) { + createWeIdForGetDoc = super.createWeIdWithSetAttr(); + } + } /** - * case: set and get weIdDom. - * - * @throws Exception may be throw Exception + * case: get weIdDom that setService and setAuthentication . */ @Test - public void testGetWeIdDocumentCase1() throws Exception { + public void testGetWeIdDocument_hasServiceAndAuthentication() { ResponseData weIdDoc = weIdService.getWeIdDocument(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); - Assert.assertNotNull(weIdDoc.getResult()); + Assert.assertEquals(2, weIdDoc.getResult().getService().size()); + Assert.assertEquals(1, weIdDoc.getResult().getAuthentication().size()); } /** - * case: set many times and get the weIdDom. - * - * @throws Exception may be throw Exception + * case: get weIdDom that setService and setAuthentication . */ @Test - public void testGetWeIdDocumentCase2() throws Exception { - - super.setPublicKey(createWeIdForGetDoc, - TestBaseUtil.createEcKeyPair()[0], - createWeIdNew.getWeId()); - super.setAuthentication(createWeIdForGetDoc, - TestBaseUtil.createEcKeyPair()[0], - createWeIdForGetDoc.getWeId()); - super.setService(createWeIdForGetDoc, - "drivingCardServic1", - "https://weidentity.webank.com/endpoint/8377465"); + public void testGetWeIdDocument_noServiceAndAuthentication() { ResponseData weIdDoc = - weIdService.getWeIdDocument(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + weIdService.getWeIdDocument(createWeIdNew.getWeId()); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); - Assert.assertNotNull(weIdDoc.getResult()); + Assert.assertEquals(1, weIdDoc.getResult().getService().size()); + Assert.assertEquals(1, weIdDoc.getResult().getAuthentication().size()); } /** - * case: weIdentity DID is invalid. - * - * @throws Exception may be throw Exception + * case: get weIdDom that setService and setAuthentication . */ @Test - public void testGetWeIdDocumentCase3() throws Exception { + public void testGetWeIdDocument_twoServiceAndAuthentication() { + CreateWeIdDataResult createWeIdResult = super.createWeId(); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData weIdDoc = weIdService.getWeIdDocument("xxxxxxxxxx"); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + ResponseData response = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); - Assert.assertNull(weIdDoc.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + + ServiceArgs setServiceArgs1 = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + setServiceArgs1.setType("1234"); + setServiceArgs1.setServiceEndpoint("http:test.com"); + + ResponseData response1 = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs1, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response1); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(true, response1.getResult()); + + ResponseData weIdDoc = + weIdService.getWeIdDocument(createWeIdResult.getWeId()); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(3, weIdDoc.getResult().getService().size()); + Assert.assertEquals(1, weIdDoc.getResult().getAuthentication().size()); } /** - * case: weIdentity DID is null. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not exists. */ @Test - public void testGetWeIdDocumentCase4() throws Exception { + public void testGetWeIdDocument_weIdUpper() { - ResponseData weIdDoc = weIdService.getWeIdDocument(null); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + String weid = createWeIdForGetDoc.getWeId(); + weid = weid.toUpperCase(); + ResponseData weIdDoc = + weIdService.getWeIdDocument(weid); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + weIdDoc.getErrorCode().intValue()); Assert.assertNull(weIdDoc.getResult()); } /** - * case: weIdentity DID is not exists. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not exists. */ @Test - public void testGetWeIdDocumentCase5() throws Exception { + public void testGetWeIdDocument_weIdExist() { ResponseData weIdDoc = weIdService.getWeIdDocument("did:weid:0xa1c93e93622c6a0b2f52c90741e0b98ab77385a9"); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), weIdDoc.getErrorCode().intValue()); @@ -139,73 +141,113 @@ public void testGetWeIdDocumentCase5() throws Exception { } /** - * case: Simulation throws an InterruptedException when calling the getLatestRelatedBlock - * method. - * - * @throws Exception may be throw Exception + * case: set many times and get the weIdDom. */ @Test - public void testGetWeIdDocumentCase6() throws Exception { - - final MockUp> mockFuture = new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future getLatestRelatedBlock(Address identity) throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testGetWeIdDocument_setRemoveManyTimes() throws Exception { + PasswordKey pwKey2 = TestBaseUtil.createEcKeyPair(); + AuthenticationArgs setAuthenticationArgs2 = new AuthenticationArgs(); + setAuthenticationArgs2.setController(createWeIdForGetDoc.getWeId()); + setAuthenticationArgs2.setPublicKey(pwKey2.getPublicKey()); + ResponseData key2Resp = weIdService.setAuthentication( + createWeIdForGetDoc.getWeId(), + setAuthenticationArgs2, + createWeIdForGetDoc.getUserWeIdPrivateKey()); + super.setService(createWeIdForGetDoc, + "drivingCardServic1", + "https://weidentity.webank.com/endpoint/8377465"); + // test cycle 1: remove + add + remove ResponseData weIdDoc = weIdService.getWeIdDocument(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); + System.out.println("1" + new ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(weIdDoc.getResult())); - mockTest.tearDown(); - mockFuture.tearDown(); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(3, weIdDoc.getResult().getService().size()); + Assert.assertEquals(2, weIdDoc.getResult().getAuthentication().size()); + + // test cycle 2: remove another pubkey and authentication + // remove the pre-created authentication + + ResponseData weIdDoc2 = weIdService + .getWeIdDocument(createWeIdForGetDoc.getWeId()); + LogUtil.info(logger, "getWeIdDocument-2", weIdDoc2); + System.out.println("2" + new ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(weIdDoc2.getResult())); + Assert.assertEquals(2, weIdDoc2.getResult().getAuthentication().size()); + + // test cycle 4: remove the authentication of a WeID while preserves its public key + AuthenticationArgs setAuthenticationArgs = new AuthenticationArgs(); + setAuthenticationArgs.setController(createWeIdForGetDoc.getWeId()); + setAuthenticationArgs + .setPublicKey(createWeIdForGetDoc.getUserWeIdPublicKey().getPublicKey()); + ResponseData res5 = weIdService.revokeAuthentication( + createWeIdForGetDoc.getWeId(), + setAuthenticationArgs, + createWeIdForGetDoc.getUserWeIdPrivateKey()); + weIdDoc2 = weIdService + .getWeIdDocument(createWeIdForGetDoc.getWeId()); + System.out.println("4" + new ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(weIdDoc2.getResult())); + LogUtil.info(logger, "getWeIdDocument-4", weIdDoc2); + Assert.assertEquals(1, weIdDoc2.getResult().getAuthentication().size()); + + // test cycle 5: add the pre-removed authentication again + ResponseData res6 = weIdService.setAuthentication( + createWeIdForGetDoc.getWeId(), + setAuthenticationArgs, + createWeIdForGetDoc.getUserWeIdPrivateKey()); + weIdDoc2 = weIdService + .getWeIdDocument(createWeIdForGetDoc.getWeId()); + System.out.println("5" + new ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(weIdDoc2.getResult())); + LogUtil.info(logger, "getWeIdDocument5", weIdDoc2); + Assert.assertEquals(2, weIdDoc2.getResult().getAuthentication().size()); + } - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - weIdDoc.getErrorCode().intValue()); + /** + * case: WeIdentity DID is invalid. + */ + @Test + public void testGetWeIdDocument_weIdInvalid() { + + ResponseData weIdDoc = weIdService.getWeIdDocument("xxxxxxxxxx"); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertNull(weIdDoc.getResult()); } /** - * case: Simulation throws an TimeoutException when calling the getLatestRelatedBlock method. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is null. */ @Test - public void testGetWeIdDocumentCase7() throws Exception { - - final MockUp> mockFuture = new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future getLatestRelatedBlock(Address identity) throws Exception { - return mockFuture.getMockInstance(); - } - }; + public void testGetWeIdDocument_weIdIsNull() { - ResponseData weIdDoc = - weIdService.getWeIdDocument(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocument result:"); - BeanUtil.print(weIdDoc); - - mockTest.tearDown(); - mockFuture.tearDown(); + ResponseData weIdDoc = weIdService.getWeIdDocument(null); + LogUtil.info(logger, "getWeIdDocument", weIdDoc); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertNull(weIdDoc.getResult()); } + + /** + * case: getWeIdList By publicKeyList. + */ + @Test + public void testGetWeIdListByPubkeyList() { + List pubKeyList = new ArrayList<>(); + int num = 5; + for (int i = 0; i < num; i++) { + WeIdPublicKey publicKey = new WeIdPublicKey(); + publicKey.setPublicKey(TestBaseUtil.createEcKeyPair().getPublicKey()); + pubKeyList.add(publicKey); + } + ResponseData weIdListRes = weIdService.getWeIdListByPubKeyList(pubKeyList); + LogUtil.info(logger, "getWeIdListByPubKeyList", weIdListRes); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdListRes.getErrorCode().intValue()); + Assert.assertEquals(num, weIdListRes.getResult().getWeIdList().size()); + } } diff --git a/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocumentJson.java b/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocumentJson.java index a6a6aa27..1ff700df 100644 --- a/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocumentJson.java +++ b/src/test/java/com/webank/weid/full/weid/TestGetWeIdDocumentJson.java @@ -1,161 +1,202 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; +import java.util.Arrays; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.response.ResponseData; +import com.webank.weid.protocol.request.AuthenticationArgs; import mockit.Mock; import mockit.MockUp; import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * getWeIdDocumentJson method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestGetWeIdDocumentJson extends TestBaseServcie { +public class TestGetWeIdDocumentJson extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestGetWeIdDocumentJson.class); + + private static CreateWeIdDataResult createWeIdForGetJson = null; + + @Override + public synchronized void testInit() { + super.testInit(); + if (createWeIdForGetJson == null) { + createWeIdForGetJson = super.createWeIdWithSetAttr(); + } + } /** - * case: success. - * - * @throws Exception may be throw Exception + * case: get and fromJson success. */ @Test - public void testGetWeIdDocumentJsonCase1() throws Exception { + public void testGetWeIdDocumentJson_withAttrSuccess() { ResponseData weIdDoc = - weIdService.getWeIdDocumentJson(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); + weIdService.getWeIdDocumentJson(createWeIdForGetJson.getWeId()); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); - Assert.assertNotNull(weIdDoc.getResult()); + WeIdDocument weIdDocument = WeIdDocument.fromJson(weIdDoc.getResult()); + Assert.assertEquals(2, weIdDocument.getService().size()); + Assert.assertEquals(1, weIdDocument.getAuthentication().size()); } /** - * case: set many times. - * - * @throws Exception may be throw Exception + * case: get and fromJson success. */ @Test - public void testGetWeIdDocumentJsonCase2() throws Exception { - - super.setPublicKey(createWeIdForGetDoc, - TestBaseUtil.createEcKeyPair()[0], - createWeIdNew.getWeId()); - super.setAuthentication(createWeIdForGetDoc, - TestBaseUtil.createEcKeyPair()[0], - createWeIdForGetDoc.getWeId()); - super.setService(createWeIdForGetDoc, - "drivingCardServic1", - "https://weidentity.webank.com/endpoint/8377465"); + public void testGetWeIdDocumentJson_noAttrSuccess() { ResponseData weIdDoc = - weIdService.getWeIdDocumentJson(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); + weIdService.getWeIdDocumentJson(super.createWeId().getWeId()); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); - Assert.assertNotNull(weIdDoc.getResult()); + WeIdDocument weIdDocument = WeIdDocument.fromJson(weIdDoc.getResult()); + Assert.assertEquals(1, weIdDocument.getService().size()); + Assert.assertEquals(1, weIdDocument.getAuthentication().size()); } /** - * case: weIdentity DID is invalid. - * - * @throws Exception may be throw Exception + * case: weid is invalid. */ @Test - public void testGetWeIdDocumentJsonCase3() throws Exception { + public void testGetWeIdDocumentJson_weIdInvalid() { - ResponseData weIdDoc = weIdService.getWeIdDocumentJson("xxxxxxxxxx"); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); + ResponseData weIdDoc = + weIdService.getWeIdDocumentJson("weid:did:123"); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); + } + + /** + * case: weid format is right but not exist. + */ + @Test + public void testGetWeIdDocumentJson_weIdNotExist() { + String weid = createWeIdForGetJson.getWeId(); + weid = weid.replace(weid.substring(weid.length() - 4, weid.length()), "ffff"); + ResponseData weIdDoc = + weIdService.getWeIdDocumentJson(weid); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); + } + /** + * case: weid UPPER. + */ + @Test + public void testGetWeIdDocumentJson_weIdIsUpper() { + String weid = createWeIdForGetJson.getWeId(); + weid = weid.toUpperCase(); + ResponseData weIdDoc = + weIdService.getWeIdDocumentJson(weid); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); } /** - * case: weIdentity DID is null. - * - * @throws Exception may be throw Exception + * case: weid is null. */ @Test - public void testGetWeIdDocumentJsonCase4() throws Exception { + public void testGetWeIdDocumentJson_weIdIsNull() { - ResponseData weIdDoc = weIdService.getWeIdDocumentJson(null); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); + ResponseData weIdDoc = + weIdService.getWeIdDocumentJson(null); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); + } + /** + * case: weid is too long . + */ + @Test + public void testGetWeIdDocumentJson_weIdIsTooLong() { + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (i % 127); + } + ResponseData weIdDoc = + weIdService.getWeIdDocumentJson(Arrays.toString(chars)); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); } /** - * case: weIdentity DID is not exists. - * - * @throws Exception may be throw Exception + * case: set many times. */ @Test - public void testGetWeIdDocumentJsonCase5() throws Exception { + public void testGetWeIdDocumentJsonCase2() { + AuthenticationArgs setAuthenticationArgs = new AuthenticationArgs(); + setAuthenticationArgs.setController(createWeIdForGetJson.getWeId()); + setAuthenticationArgs.setPublicKey(TestBaseUtil.createEcKeyPair().getPublicKey()); + weIdService.setAuthentication(createWeIdForGetJson.getWeId(), + setAuthenticationArgs, + createWeIdForGetJson.getUserWeIdPrivateKey()); + super.setService(createWeIdForGetJson, + "drivingCardServic1", + "https://weidentity.webank.com/endpoint/8377465"); ResponseData weIdDoc = - weIdService.getWeIdDocumentJson("did:weid:0xa1c93e93622c6a0b2f52c90741e0b98ab77385a9"); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); + weIdService.getWeIdDocumentJson(createWeIdForGetJson.getWeId()); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); - Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), - weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertNotNull(weIdDoc.getResult()); + } + + /** + * case: WeIdentity DID is invalid. + */ + @Test + public void testGetWeIdDocumentJsonCase3() { + + ResponseData weIdDoc = weIdService.getWeIdDocumentJson("xxxxxxxxxx"); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); } /** - * case: Simulation throws an Exception when calling the - * writerWithDefaultPrettyPrinter method. - * - * @throws Exception may be throw Exception + * case: Simulation throws an Exception when calling the writerWithDefaultPrettyPrinter method. */ @Test - public void testGetWeIdDocumentJsonCase6() throws Exception { + public void testGetWeIdDocumentJsonCase6() { - MockUp mockTest = new MockUp() { + new MockUp() { @Mock - public ObjectWriter writerWithDefaultPrettyPrinter() throws Exception { - throw new Exception("excpetion"); + public ObjectWriter writerWithDefaultPrettyPrinter() { + return null; } }; ResponseData weIdDoc = - weIdService.getWeIdDocumentJson(createWeIdForGetDoc.getWeId()); - System.out.println("\ngetWeIdDocumentJson result:"); - BeanUtil.print(weIdDoc); - - mockTest.tearDown(); + weIdService.getWeIdDocumentJson(createWeIdForGetJson.getWeId()); + LogUtil.info(logger, "getWeIdDocumentJson", weIdDoc); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); Assert.assertEquals(StringUtils.EMPTY, weIdDoc.getResult()); diff --git a/src/test/java/com/webank/weid/full/weid/TestIsWeIdExist.java b/src/test/java/com/webank/weid/full/weid/TestIsWeIdExist.java index 61848c3d..1a899e8e 100644 --- a/src/test/java/com/webank/weid/full/weid/TestIsWeIdExist.java +++ b/src/test/java/com/webank/weid/full/weid/TestIsWeIdExist.java @@ -1,203 +1,116 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.protocol.response.ResponseData; -import java.util.concurrent.Future; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.Bool; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * isWeIdExist method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestIsWeIdExist extends TestBaseServcie { +public class TestIsWeIdExist extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestIsWeIdExist.class); /** - * case: weIdentity DID is Exist. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is Exist. */ @Test - public void testIsWeIdExistCase1() { + public void testIsWeIdExist_sucess() { - ResponseData response1 = weIdService.isWeIdExist(createWeId.getWeId()); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + ResponseData response1 = weIdService.isWeIdExist(createWeIdResult.getWeId()); + LogUtil.info(logger, "isWeIdExist", response1); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(true, response1.getResult()); } /** - * case: weIdentity DID is empty. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not Exist. */ @Test - public void testIsWeIdExistCase2() { + public void testIsWeIdExist_weIdNotExist() { - ResponseData response1 = weIdService.isWeIdExist(null); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + String weId = createWeIdResult.getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), "fefe"); + ResponseData response1 = weIdService.isWeIdExist(weId); + LogUtil.info(logger, "isWeIdExist", response1); - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: weIdentity DID is invalid. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is empty. */ @Test - public void testIsWeIdExistCase3() { + public void testIsWeIdExist_weIdNull() { - ResponseData response1 = weIdService.isWeIdExist("xxxxxx"); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + ResponseData response1 = weIdService.isWeIdExist(null); + LogUtil.info(logger, "isWeIdExist", response1); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: weIdentity DID is not exist. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is blank. */ @Test - public void testIsWeIdExistCase4() { + public void testIsWeIdExist_weIdBlank() { - ResponseData response1 = weIdService.isWeIdExist("did:weid:xxxxxx"); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + ResponseData response1 = weIdService.isWeIdExist(""); + LogUtil.info(logger, "isWeIdExist", response1); - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: weIdentity DID is Exist. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is invalid. */ @Test - public void testIsWeIdExistCase5() throws Exception { - - ResponseData response1 = weIdService.isWeIdExist(createWeId.getWeId()); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + public void testIsWeIdExist_invalidWeId() { - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); - Assert.assertEquals(true, response1.getResult()); - } - - /** - * case: Simulation throws an TimeoutException when calling the isIdentityExist - * method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testIsWeIdExistCase6() { - - MockUp mockTest = new MockUp() { - @Mock - public Future isIdentityExist(Address identity) throws Exception { - throw new TimeoutException(); - } - }; - - ResponseData response1 = weIdService.isWeIdExist(createWeId.getWeId()); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); - - mockTest.tearDown(); + ResponseData response1 = weIdService.isWeIdExist("xxxxxx"); + LogUtil.info(logger, "isWeIdExist", response1); - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response1.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: Simulation throws an InterruptedException when calling the isIdentityExist - * method. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID contain zh. */ @Test - public void testIsWeIdExistCase7() { - - MockUp mockTest = new MockUp() { - @Mock - public Future isIdentityExist(Address identity) throws Exception { - throw new InterruptedException(); - } - }; - - ResponseData response1 = weIdService.isWeIdExist(createWeId.getWeId()); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + public void testIsWeIdExist_weIdZh() { - mockTest.tearDown(); + ResponseData response1 = weIdService.isWeIdExist("你好"); + LogUtil.info(logger, "isWeIdExist", response1); - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response1.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response1.getErrorCode().intValue()); Assert.assertEquals(false, response1.getResult()); } /** - * case: Simulation throws an NullPointerException when calling the isIdentityExist - * method. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is Exist. */ @Test - public void testIsWeIdExistCase8() { - - MockUp mockTest = new MockUp() { - @Mock - public Future isIdentityExist(Address identity) throws Exception { - throw new NullPointerException(); - } - }; + public void testIsWeIdExistCase5() { - ResponseData response1 = weIdService.isWeIdExist(createWeId.getWeId()); - System.out.println("\nisWeIdExist result:"); - BeanUtil.print(response1); + ResponseData response1 = weIdService.isWeIdExist(createWeIdResult.getWeId()); + LogUtil.info(logger, "isWeIdExist", response1); - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response1.getErrorCode().intValue()); - Assert.assertEquals(false, response1.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(true, response1.getResult()); } } diff --git a/src/test/java/com/webank/weid/full/weid/TestSetAuthentication.java b/src/test/java/com/webank/weid/full/weid/TestSetAuthentication.java index 8d61e8a2..779c0694 100644 --- a/src/test/java/com/webank/weid/full/weid/TestSetAuthentication.java +++ b/src/test/java/com/webank/weid/full/weid/TestSetAuthentication.java @@ -1,171 +1,185 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.response.ResponseData; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.AuthenticationArgs; +import com.webank.weid.protocol.response.CreateWeIdDataResult; +import com.webank.weid.blockchain.protocol.response.ResponseData; +import com.webank.weid.util.DateUtils; /** * setAuthentication method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestSetAuthentication extends TestBaseServcie { +public class TestSetAuthentication extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestSetAuthentication.class); + + @Override + public synchronized void testInit() { + super.testInit(); + } /** - * case: set success. - * - * @throws Exception may be throw Exception + * case: publicKey repeat, set failed. */ @Test - public void testSetAuthenticationCase1() throws Exception { + public void testSetAuthentication_setAuthenticationSuccess() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); + + Assert.assertEquals(ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); } /** - * case: weIdentity DID is blank. - * - * @throws Exception may be throw Exception + * case: set two Authentication success. */ @Test - public void testSetAuthenticationCase2() throws Exception { + public void testSetAuthentication_setTwoAuthenticationSuccess() { + + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdNew); + ResponseData response = weIdService.setAuthentication( + createWeIdNew.getWeId(), + setAuthenticationArgs, + createWeIdNew.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); + Assert.assertEquals(ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setWeId(null); + AuthenticationArgs setAuthenticationArgs1 = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdNew); + setAuthenticationArgs1.setController(createWeIdResult.getWeId()); + ResponseData response1 = weIdService.setAuthentication( + createWeIdNew.getWeId(), + setAuthenticationArgs1, + createWeIdNew.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response1); + Assert.assertEquals(ErrorCode.AUTHENTICATION_PUBLIC_KEY_MULTIBASE_EXISTS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(false, response1.getResult()); + + ResponseData weIdDoc = + weIdService.getWeIdDocument(createWeIdNew.getWeId()); + LogUtil.info(logger, "setAuthentication", weIdDoc); + Assert.assertEquals(1, weIdDoc.getResult().getAuthentication().size()); + } - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + /** + * case: WeIdentity DID is blank. + */ + @Test + public void testSetAuthentication_weIdBlank() { + + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + + ResponseData response = weIdService.setAuthentication("", + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DID is bad format. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testSetAuthenticationCase3() throws Exception { + public void testSetAuthentication_weIdFormat() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setWeId("di:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac73"); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + "di:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac73", + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DID is not exists. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not exists. */ @Test - public void testSetAuthenticationCase4() throws Exception { + public void testSetAuthentication_weIdNotExist() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setWeId("did:weid:0xbb"); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + "did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431", + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: type is null or other string. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID contain zh. */ @Test - public void testSetAuthenticationCase5() throws Exception { + public void testSetAuthentication_weIdContainZh() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setType(null); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + "did:weid:你好", + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** * case: publicKey is a new key. - * - * @throws Exception may be throw Exception */ @Test - public void testSetAuthenticationCase6() throws Exception { + public void testSetAuthentication_newPubKey() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - String[] pk = TestBaseUtil.createEcKeyPair(); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); - setAuthenticationArgs.setPublicKey(pk[0]); + setAuthenticationArgs.setPublicKey(passwordKey.getPublicKey()); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); @@ -173,100 +187,96 @@ public void testSetAuthenticationCase6() throws Exception { /** * case: publicKey is null. - * - * @throws Exception may be throw Exception */ @Test - public void testSetAuthenticationCase7() throws Exception { + public void testSetAuthentication_PubKeyNull() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); setAuthenticationArgs.setPublicKey(null); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: publicKey is invalid ("xxxxxxxxxx" or "1111111111111"). - * - * @throws Exception may be throw Exception + * case: publicKey is belong other weId. */ @Test - public void testSetAuthenticationCase8() throws Exception { + public void testSetAuthentication_PubKeyOther() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setPublicKey("xxxxxxxxxxxx"); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + String newPubkey = createWeIdNew.getUserWeIdPublicKey().getPublicKey(); + setAuthenticationArgs.setPublicKey(newPubkey); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } /** - * case: userWeIdPrivateKey is null. - * - * @throws Exception may be throw Exception + * case: publicKey is invalid ("xxxxxxxxxx" or "1111111111111"). */ @Test - public void testSetAuthenticationCase9() throws Exception { + public void testSetAuthentication_pubKeyxxx() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setUserWeIdPrivateKey(null); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setPublicKey("xxxxxxxxxxxx"); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); } /** - * case: privateKey is null. - * - * @throws Exception may be throw Exception + * case: publicKey contain special character. */ @Test - public void testSetAuthenticationCase10() throws Exception { + public void testSetAuthentication_pubKeySpecialChar() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.getUserWeIdPrivateKey().setPrivateKey(null); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setPublicKey("~!@#¥%……&*?》《;az09"); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey is invalid. - * - * @throws Exception may be throw Exception + * case: userWeIdPrivateKey is null. */ @Test - public void testSetAuthenticationCase11() throws Exception { + public void testSetAuthentication_priKeyNull() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.getUserWeIdPrivateKey().setPrivateKey("xxxxxxxxxxxxxxxxxxx"); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, null); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); @@ -274,42 +284,39 @@ public void testSetAuthenticationCase11() throws Exception { } /** - * case: privateKey and privateKey of weIdentity DID does not match. - * - * @throws Exception may be throw Exception + * case: privateKey is invalid. */ @Test - public void testSetAuthenticationCase12() throws Exception { + public void testSetAuthentication_invalidPriKey() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - String[] pk = TestBaseUtil.createEcKeyPair(); - setAuthenticationArgs.getUserWeIdPrivateKey().setPrivateKey(pk[1]); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication(createWeIdResult.getWeId(), + setAuthenticationArgs, + new WeIdPrivateKey("xxxxxxxxxxxxxxxxxxxxx")); + LogUtil.info(logger, "setAuthentication", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey belongs to the private key of other weIdentity DID. - * - * @throws Exception may be throw Exception + * case: privateKey and privateKey of WeIdentity DID does not match. */ @Test - public void testSetAuthenticationCase13() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setUserWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + public void testSetAuthentication_newPriKey() { + + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); + setAuthenticationArgs.setPublicKey(passwordKey.getPublicKey()); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), + setAuthenticationArgs, + new WeIdPrivateKey(passwordKey.getPrivateKey())); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); @@ -317,20 +324,18 @@ public void testSetAuthenticationCase13() throws Exception { } /** - * case: other weIdentity DID. - * - * @throws Exception may be throw Exception + * case: other WeIdentity DID. */ @Test - public void testSetAuthenticationCase14() throws Exception { + public void testSetAuthentication_otherWeid() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setWeId(createWeIdNew.getWeId()); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdNew.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); @@ -338,199 +343,183 @@ public void testSetAuthenticationCase14() throws Exception { } /** - * case: owner is the weIdentity DID. - * - * @throws Exception may be throw Exception + * case: owner is other WeIdentity DID. */ @Test - public void testSetAuthenticationCase15() throws Exception { + public void testSetAuthentication_ownerIsOtherWeId() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setOwner(setAuthenticationArgs.getWeId()); - - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setController(createWeIdNew.getWeId()); + setAuthenticationArgs.setPublicKey(createWeIdNew.getUserWeIdPublicKey().getPublicKey()); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } /** - * case: owner is other weIdentity DID. - * - * @throws Exception may be throw Exception + * case: owner is the WeIdentity DID. */ @Test - public void testSetAuthenticationCase16() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setOwner(createWeIdNew.getWeId()); + public void testSetAuthentication_owerNotExist() { + String weId = createWeId().getWeId(); + weId = weId.replace(weId.substring(weId.length() - 4, weId.length()), + DateUtils.getNoMillisecondTimeStampString()); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setController(weId); + + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(false, response.getResult()); + } + /** + * case: owner is the WeIdentity DID. + */ + @Test + public void testSetAuthentication_twoAuthentication() { + + final String weid1 = createWeId().getWeId(); + final String weid2 = createWeId().getWeId(); + CreateWeIdDataResult createWeIdResultWithSetAttr = super.createWeId(); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResultWithSetAttr); + setAuthenticationArgs.setController(weid1); + setAuthenticationArgs.setPublicKey(createWeId().getUserWeIdPublicKey().getPublicKey()); + ResponseData response = weIdService.setAuthentication( + createWeIdResultWithSetAttr.getWeId(), + setAuthenticationArgs, + createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); + + AuthenticationArgs setAuthenticationArgs1 = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResultWithSetAttr); + setAuthenticationArgs1.setController(weid2); + setAuthenticationArgs1.setPublicKey("12345678"); + ResponseData res = weIdService.setAuthentication( + createWeIdResultWithSetAttr.getWeId(), + setAuthenticationArgs1, + createWeIdResultWithSetAttr.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", res); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), res.getErrorCode().intValue()); + + ResponseData weIdDoc = + weIdService.getWeIdDocument(createWeIdResultWithSetAttr.getWeId()); + LogUtil.info(logger, "setAuthentication", weIdDoc); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(3, weIdDoc.getResult().getAuthentication().size()); } /** * case: owner is invalid. - * - * @throws Exception may be throw Exception */ @Test - public void testSetAuthenticationCase17() throws Exception { + public void testSetAuthentication_invalidOwner() { - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - setAuthenticationArgs.setOwner("xxxxxxxxxxxxxxxxx"); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setController("xxxxxxxxxxxxxxxxx"); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: Simulation throws an InterruptedException when calling the - * setAttribute method. - * - * @throws Exception may be throw Exception + * case: owner is null. */ @Test - public void testSetAuthenticationCase18() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + public void testSetAuthentication_ownerNull() { + + final CreateWeIdDataResult weId = super.createWeId(); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(weId); + setAuthenticationArgs.setController(null); + + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); + + ResponseData weIdDoc + = weIdService.getWeIdDocument(weId.getWeId()); + LogUtil.info(logger, "setAuthentication", weIdDoc); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(1, weIdDoc.getResult().getAuthentication().size()); } /** - * case: Simulation throws an TimeoutException when calling the - * setAttribute method. - * - * @throws Exception may be throw Exception + * case: owner is blank. */ @Test - public void testSetAuthenticationCase19() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + public void testSetAuthentication_ownerBlank() { + + final CreateWeIdDataResult weId = super.createWeId(); + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setController(""); + setAuthenticationArgs.setPublicKey(weId.getUserWeIdPublicKey().getPublicKey()); + + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); + + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); } /** - * case: Simulation throws an NullPointerException when calling the - * getWeIdAttributeChangedEvents method. - * - * @throws Exception may be throw Exception + * case: owner contain special char. */ @Test - public void testSetAuthenticationCase20() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = - TestBaseUtil.buildSetAuthenticationArgs(createWeId); + public void testSetAuthentication_ownerContainSpecialChar() { - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - throw new NullPointerException(); - } - }; + AuthenticationArgs setAuthenticationArgs = + TestBaseUtil.buildSetAuthenticationArgs(createWeIdResult); + setAuthenticationArgs.setController("~!@#$%^&*()——+=?》《,<>aq10"); - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication( + createWeIdResult.getWeId(), setAuthenticationArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + /** * case: setAuthenticationArgs is null. - * - * @throws Exception may be throw Exception */ @Test - public void testSetAuthenticationCase21() throws Exception { + public void testSetAuthenticationCase21() { - ResponseData response = weIdService.setAuthentication(null); - System.out.println("\nsetAuthentication result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setAuthentication(createWeIdResult.getWeId(), + null, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setAuthentication", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + } diff --git a/src/test/java/com/webank/weid/full/weid/TestSetPublicKey.java b/src/test/java/com/webank/weid/full/weid/TestSetPublicKey.java deleted file mode 100644 index 9e15f4ba..00000000 --- a/src/test/java/com/webank/weid/full/weid/TestSetPublicKey.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.full.weid; - -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.response.ResponseData; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Assert; -import org.junit.Test; - -/** - * setPublicKey method for testing WeIdService. - * - * @author v_wbgyang - * - */ -public class TestSetPublicKey extends TestBaseServcie { - - /** - * case: create success. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase1() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * case: weIdentity DID is blank. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase2() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setWeId(null); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: weIdentity DID is bad format. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase3() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setWeId("di:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac73"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: weIdentity DID is not exists. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase4() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setWeId("did:weid:0aaaaaaaaaaaa"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: type is null or other string. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase5() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setType(null); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: publicKey is a new key. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase6() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - String[] pk = TestBaseUtil.createEcKeyPair(); - - setPublicKeyArgs.setPublicKey(pk[0]); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * case: publicKey is null. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase7() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setPublicKey(null); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: publicKey is invalid ("xxxxxxxxxx" or "1111111111111"). - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase8() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setPublicKey("xxxxxxxxxxxxxxxxxxx"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * case: userWeIdPrivateKey is null. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase9() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setUserWeIdPrivateKey(null); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: privateKey is null. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase10() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.getUserWeIdPrivateKey().setPrivateKey(null); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: privateKey is invalid. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase11() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.getUserWeIdPrivateKey().setPrivateKey("xxxxxxxxxxxxxxxxxxx"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: privateKey and privateKey of weIdentity DID does not match. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase12() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - String[] pk = TestBaseUtil.createEcKeyPair(); - setPublicKeyArgs.getUserWeIdPrivateKey().setPrivateKey(pk[1]); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: the private key belongs to the private key of other weIdentity DID. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase13() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setUserWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: other weIdentity DID. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase14() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setWeId(createWeIdNew.getWeId()); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: owner is the weIdentity DID. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase15() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setOwner(setPublicKeyArgs.getWeId()); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * case: owner is other weIdentity DID. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase16() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setOwner(createWeIdNew.getWeId()); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(true, response.getResult()); - } - - /** - * case: owner is invalid. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase17() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - setPublicKeyArgs.setOwner("xxxxxxxxxxxxxxxxx"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: Simulation throws an InterruptedException when calling the - * setPublicKey method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase18() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: Simulation throws an TimeoutException when calling the - * setAttribute method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase19() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: Simulation throws an InterruptedException when calling the - * setAttribute method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase20() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = TestBaseUtil.buildSetPublicKeyArgs(createWeId); - - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - throw new NullPointerException(); - } - }; - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } - - /** - * case: setAuthenticationArgs is null. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetPublicKeyCase21() throws Exception { - - ResponseData response = weIdService.setPublicKey(null); - System.out.println("\nsetPublicKey result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } -} diff --git a/src/test/java/com/webank/weid/full/weid/TestSetService.java b/src/test/java/com/webank/weid/full/weid/TestSetService.java index 21367f5d..98efa6bd 100644 --- a/src/test/java/com/webank/weid/full/weid/TestSetService.java +++ b/src/test/java/com/webank/weid/full/weid/TestSetService.java @@ -1,304 +1,273 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.full.weid; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.constant.ErrorCode; -import com.webank.weid.contract.WeIdContract; -import com.webank.weid.contract.WeIdContract.WeIdAttributeChangedEventResponse; -import com.webank.weid.full.TestBaseServcie; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.response.ResponseData; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import mockit.Mock; -import mockit.MockUp; -import org.bcos.web3j.abi.datatypes.Address; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.LogUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.full.TestBaseService; +import com.webank.weid.full.TestBaseUtil; +import com.webank.weid.protocol.base.WeIdDocument; +import com.webank.weid.protocol.base.WeIdPrivateKey; +import com.webank.weid.protocol.request.ServiceArgs; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * setService method for testing WeIdService. - * - * @author v_wbgyang * + * @author v_wbgyang */ -public class TestSetService extends TestBaseServcie { +public class TestSetService extends TestBaseService { + + private static final Logger logger = LoggerFactory.getLogger(TestSetService.class); + + @Override + public synchronized void testInit() { + super.testInit(); + } /** * case: set success. - * - * @throws Exception may be throw Exception */ @Test - public void testSetServiceCase1() throws Exception { + public void testSetService_sucess() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(true, response.getResult()); } /** - * case: weIdentity DID is blank. - * - * @throws Exception may be throw Exception + * case: two services(type different) set success. */ @Test - public void testSetServiceCase2() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setWeId(null); + public void testSetService_twoTypeDifferentServices() { - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + ResponseData response = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - /** - * case: weIdentity DID is bad format. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetServiceCase3() throws Exception { + ServiceArgs setServiceArgs1 = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + setServiceArgs1.setType("1234"); + ResponseData response1 = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs1, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(true, response1.getResult()); - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setWeId("di:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac73"); + ResponseData weIdDoc = + weIdService.getWeIdDocument(createWeIdResult.getWeId()); + LogUtil.info(logger, "setService", weIdDoc); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(3, weIdDoc.getResult().getService().size()); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); } /** - * case: weIdentity DID is not exists. - * - * @throws Exception may be throw Exception + * case: two services(endpoint different) set success. */ @Test - public void testSetServiceCase4() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setWeId("did:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac7a"); + public void testSetService_twoEndpointDifferentServices() { - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + ResponseData response = weIdService.setService(createWeIdResult.getWeId(), + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(true, response.getResult()); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); + ServiceArgs setServiceArgs1 = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + setServiceArgs1.setServiceEndpoint("http:test.com"); + ResponseData response1 = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs1, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response1); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), response1.getErrorCode().intValue()); + Assert.assertEquals(true, response1.getResult()); + + ResponseData weIdDoc = + weIdService.getWeIdDocument(createWeIdResult.getWeId()); + LogUtil.info(logger, "setService", weIdDoc); + Assert.assertEquals(ErrorCode.SUCCESS.getCode(), weIdDoc.getErrorCode().intValue()); + Assert.assertEquals(3, weIdDoc.getResult().getService().size()); } /** - * case: type is null. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is blank. */ @Test - public void testSetServiceCase5() throws Exception { + public void testSetService_weIdIsNull() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setType(null); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService(null, setServiceArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: type too long. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is bad format. */ @Test - public void testSetServiceCase6() throws Exception { + public void testSetService_invalidWeId() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs - .setType("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService("di:weid:0xsdg!@#$%^&《》", + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: serviceEndpoint is null (or " "). - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is not exists. */ @Test - public void testSetServiceCase7() throws Exception { + public void testSetService_weIdNotExist() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setServiceEndpoint(null); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + "did:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac7a", + setServiceArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_DOES_NOT_EXIST.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: userWeIdPrivateKey is null. - * - * @throws Exception may be throw Exception + * case: WeIdentity DID is too long. */ @Test - public void testSetServiceCase8() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setUserWeIdPrivateKey(null); - - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - - Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); + public void testSetService_weIdTooLong() { + + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + char[] chars = new char[1000]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) (i % 127); + } + String weId = String.valueOf(chars); + weId = "did:weid:0xbbd97a63365b6c9fb6b011a8d294307a3b7dac7" + weId; + ResponseData response = weIdService.setService(weId, setServiceArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); + + Assert.assertEquals(ErrorCode.WEID_INVALID.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey is null. - * - * @throws Exception may be throw Exception + * case: other WeIdentity DID. */ @Test - public void testSetServiceCase9() throws Exception { + public void testSetService_otherWeId() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.getUserWeIdPrivateKey().setPrivateKey(null); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService(createWeIdNew.getWeId(), + setServiceArgs, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the private key belongs to other weIdentity DID. - * - * @throws Exception may be throw Exception + * case: type is null. */ @Test - public void testSetServiceCase10() throws Exception { + public void testSetService_typeNull() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - - setServiceArgs.setUserWeIdPrivateKey(createWeIdNew.getUserWeIdPrivateKey()); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + setServiceArgs.setType(null); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: the private key does not match the current weId. - * - * @throws Exception may be throw Exception + * case: serviceEndpoint is null. */ @Test - public void testSetServiceCase11() throws Exception { + public void testSetService_endpointNull() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.getUserWeIdPrivateKey().setPrivateKey("11111111111111"); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + setServiceArgs.setServiceEndpoint(null); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), - response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: privateKey and privateKey of weIdentity DID do not match. - * - * @throws Exception may be throw Exception + * case: userWeIdPrivateKey is null. */ @Test - public void testSetServiceCase12() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); + public void testSetService_priKeyNull() { - String[] pk = TestBaseUtil.createEcKeyPair(); - setServiceArgs.getUserWeIdPrivateKey().setPrivateKey(pk[1]); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + null); + LogUtil.info(logger, "setService", response); - Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } + /** - * case: other weIdentity DID. - * - * @throws Exception may be throw Exception + * case: the private key belongs to other WeIdentity DID. */ @Test - public void testSetServiceCase13() throws Exception { + public void testSetService_priKeyIsOtherWeid() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.setWeId(createWeIdNew.getWeId()); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + createWeIdNew.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); @@ -306,134 +275,53 @@ public void testSetServiceCase13() throws Exception { } /** - * case: Simulation throws an InterruptedException when calling the - * setService method. - * - * @throws Exception may be throw Exception + * case: the private key does not match the current weId. */ @Test - public void testSetServiceCase14() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new InterruptedException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_EXECUTE_ERROR.getCode(), - response.getErrorCode().intValue()); - Assert.assertEquals(false, response.getResult()); - } + public void testSetService_prikeyNotMatch() { - /** - * case: Simulation throws an TimeoutException when calling the - * setService method. - * - * @throws Exception may be throw Exception - */ - @Test - public void testSetServiceCase15() throws Exception { - - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - - final MockUp> mockFuture = - new MockUp>() { - @Mock - public Future get(long timeout, TimeUnit unit) - throws Exception { - throw new TimeoutException(); - } - }; - - MockUp mockTest = new MockUp() { - @Mock - public Future setAttribute( - Address identity, - Bytes32 key, - DynamicBytes value, - Int256 updated) - throws Exception { - return mockFuture.getMockInstance(); - } - }; - - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - mockFuture.tearDown(); - - Assert.assertEquals(ErrorCode.TRANSACTION_TIMEOUT.getCode(), + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + new WeIdPrivateKey("111111111")); + LogUtil.info(logger, "setService", response); + + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** - * case: Simulation throws an NullPointerException when calling the - * setService method. - * - * @throws Exception may be throw Exception + * case: privateKey and privateKey of WeIdentity DID do not match. */ @Test - public void testSetServiceCase16() throws Exception { + public void testSetServiceCase12() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); + PasswordKey passwordKey = TestBaseUtil.createEcKeyPair(); - MockUp mockTest = new MockUp() { - @Mock - public List getWeIdAttributeChangedEvents( - TransactionReceipt transactionReceipt) - throws Exception { - throw new NullPointerException(); - } - }; + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), + setServiceArgs, + new WeIdPrivateKey(passwordKey.getPrivateKey())); + LogUtil.info(logger, "setService", response); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); - - mockTest.tearDown(); - - Assert.assertEquals(ErrorCode.UNKNOW_ERROR.getCode(), response.getErrorCode().intValue()); + Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_DOES_NOT_MATCH.getCode(), + response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); } /** * case: setServiceArgs is null. - * - * @throws Exception may be throw Exception */ @Test - public void testSetServiceCase17() throws Exception { + public void testSetServiceCase17() { - ResponseData response = weIdService.setService(null); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService(createWeIdResult.getWeId(), + null, createWeIdResult.getUserWeIdPrivateKey()); + LogUtil.info(logger, "setService", response); Assert.assertEquals(ErrorCode.ILLEGAL_INPUT.getCode(), response.getErrorCode().intValue()); Assert.assertEquals(false, response.getResult()); @@ -441,18 +329,15 @@ public void testSetServiceCase17() throws Exception { /** * case: private key is invalid. - * - * @throws Exception may be throw Exception */ @Test - public void testSetServiceCase18() throws Exception { + public void testSetServiceCase18() { - SetServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeId); - setServiceArgs.getUserWeIdPrivateKey().setPrivateKey("xxxxxxxxxxxxxxx"); + ServiceArgs setServiceArgs = TestBaseUtil.buildSetServiceArgs(createWeIdResult); - ResponseData response = weIdService.setService(setServiceArgs); - System.out.println("\nsetService result:"); - BeanUtil.print(response); + ResponseData response = weIdService.setService( + createWeIdResult.getWeId(), setServiceArgs, new WeIdPrivateKey("xxxxxxx")); + LogUtil.info(logger, "setService", response); Assert.assertEquals(ErrorCode.WEID_PRIVATEKEY_INVALID.getCode(), response.getErrorCode().intValue()); diff --git a/src/test/java/com/webank/weid/performance/TestWeIdPerformance.java b/src/test/java/com/webank/weid/performance/TestWeIdPerformance.java index dcc3a622..771f88ef 100644 --- a/src/test/java/com/webank/weid/performance/TestWeIdPerformance.java +++ b/src/test/java/com/webank/weid/performance/TestWeIdPerformance.java @@ -1,77 +1,70 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.performance; +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.webank.weid.BaseTest; -import com.webank.weid.constant.ErrorCode; +import com.webank.weid.blockchain.constant.ErrorCode; import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.SetServiceArgs; +import com.webank.weid.protocol.request.ServiceArgs; import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import org.junit.Test; +import com.webank.weid.blockchain.protocol.response.ResponseData; /** * performance testing. - * - * @author v_wbgyang * + * @author v_wbgyang */ public class TestWeIdPerformance extends BaseTest { + private static final Logger logger = LoggerFactory.getLogger(TestWeIdPerformance.class); + @Test - public void testGetWeIdDom() throws Exception { + public void testGetWeIdDom() throws IOException { - System.out.println("blockNumber:" + this.getBlockNumber()); + logger.info("blockNumber:{}", com.webank.weid.blockchain.util.DataToolUtils.getBlockNumber()); CreateWeIdDataResult weIdResult = this.createWeId(); - System.out.println("weIdentity DID:" + weIdResult.getWeId()); + logger.info("WeIdentity DID:{}", weIdResult.getWeId()); int count = 1; for (int i = 0; i < count; i++) { - this.setService(weIdResult, + this.setService( + weIdResult, "driving" + i, - "https://weidentity.webank.com/endpoint/8377464" + i); - System.out.println("------" + i); + "https://weidentity.webank.com/endpoint/8377464" + i + ); } - System.out.println("blockNumber:" + this.getBlockNumber()); + logger.info("blockNumber:{}", com.webank.weid.blockchain.util.DataToolUtils.getBlockNumber()); long startTime = System.currentTimeMillis(); WeIdDocument result = this.getWeIdDom(weIdResult.getWeId()); - System.out.println(result.getService().size()); + logger.info(String.valueOf(result.getService().size())); long gasTime = System.currentTimeMillis() - startTime; - System.out.println("use time:" + gasTime + "ms"); + logger.info("use time:{}ms", gasTime); + + Assert.assertNotNull(result); } /** - * create weIdentity DID. + * create WeIdentity DID. */ - public CreateWeIdDataResult createWeId() throws RuntimeException { + public CreateWeIdDataResult createWeId() { - // create weIdentity DID,publicKey,privateKey + // create WeIdentity DID,publicKey,privateKey ResponseData responseCreate = weIdService.createWeId(); // check result is success if (responseCreate.getErrorCode() != ErrorCode.SUCCESS.getCode()) { - throw new RuntimeException(responseCreate.getErrorMessage()); + logger.info("createWeId fail :{}", responseCreate.getErrorMessage()); + Assert.assertTrue(false); } return responseCreate.getResult(); } @@ -82,36 +75,34 @@ public CreateWeIdDataResult createWeId() throws RuntimeException { public void setService( CreateWeIdDataResult createResult, String serviceType, - String serviceEnpoint) - throws RuntimeException { + String serviceEnpoint) { - // setService for this weIdentity DID - SetServiceArgs setServiceArgs = new SetServiceArgs(); - setServiceArgs.setWeId(createResult.getWeId()); + // setService for this WeIdentity DID + ServiceArgs setServiceArgs = new ServiceArgs(); setServiceArgs.setType(serviceType); setServiceArgs.setServiceEndpoint(serviceEnpoint); - setServiceArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setServiceArgs.getUserWeIdPrivateKey() - .setPrivateKey(createResult.getUserWeIdPrivateKey().getPrivateKey()); - ResponseData responseSetSer = weIdService.setService(setServiceArgs); + ResponseData responseSetSer = weIdService.setService(createResult.getWeId(), + setServiceArgs, createResult.getUserWeIdPrivateKey()); // check is success if (responseSetSer.getErrorCode() != ErrorCode.SUCCESS.getCode() || !responseSetSer.getResult()) { - throw new RuntimeException(responseSetSer.getErrorMessage()); + logger.info("setService fail :{}", responseSetSer.getErrorMessage()); + Assert.assertTrue(false); } } /** * getWeIdDom. */ - public WeIdDocument getWeIdDom(String weId) throws RuntimeException { + public WeIdDocument getWeIdDom(String weId) { // get weIdDom ResponseData responseResult = weIdService.getWeIdDocument(weId); // check result if (responseResult.getErrorCode() != ErrorCode.SUCCESS.getCode() || responseResult.getResult() == null) { - throw new RuntimeException(responseResult.getErrorMessage()); + logger.info("getWeIdDocument fail :{}", responseResult.getErrorMessage()); + Assert.assertTrue(false); } return responseResult.getResult(); } diff --git a/src/test/java/com/webank/weid/service/TestAuthorityIssuerService.java b/src/test/java/com/webank/weid/service/TestAuthorityIssuerService.java deleted file mode 100644 index cc9f7bab..00000000 --- a/src/test/java/com/webank/weid/service/TestAuthorityIssuerService.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.service; - -import com.webank.weid.BaseTest; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.full.TestBaseUtil; -import com.webank.weid.protocol.base.AuthorityIssuer; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.RegisterAuthorityIssuerArgs; -import com.webank.weid.protocol.request.RemoveAuthorityIssuerArgs; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.rpc.AuthorityIssuerService; -import java.util.Date; -import org.junit.Assert; -import org.junit.Test; - -/** - * test AuthorityIssuerService. - * - * @author v_wbgyang - */ -@SuppressWarnings("all") -public class TestAuthorityIssuerService extends BaseTest { - - /** - * test AuthorityIssuerService.registerAuthorityIssuer. - */ - @Test - public void testRegisterAuthorityIssuer() throws Exception { - - RegisterAuthorityIssuerArgs registerAuthorityIssuerArgs = new RegisterAuthorityIssuerArgs(); - registerAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - registerAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(TestBaseUtil.privKey); - - AuthorityIssuer authorityIssuer = new AuthorityIssuer(); - registerAuthorityIssuerArgs.setAuthorityIssuer(authorityIssuer); - - authorityIssuer.setWeId("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - authorityIssuer.setCreated(new Date().getTime()); - authorityIssuer.setName("webank1"); - authorityIssuer.setAccValue("0"); - - ResponseData response = - authorityIssuerService.registerAuthorityIssuer(registerAuthorityIssuerArgs); - BeanUtil.print(response); - } - - /** - * test AuthorityIssuerService.removeAuthorityIssuer. - */ - @Test - public void testRemoveAuthorityIssuer() throws Exception { - - RemoveAuthorityIssuerArgs removeAuthorityIssuerArgs = new RemoveAuthorityIssuerArgs(); - removeAuthorityIssuerArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - removeAuthorityIssuerArgs.getWeIdPrivateKey().setPrivateKey(TestBaseUtil.privKey); - - removeAuthorityIssuerArgs.setWeId("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - - ResponseData response = - authorityIssuerService.removeAuthorityIssuer(removeAuthorityIssuerArgs); - BeanUtil.print(response); - } - - /** - * test AuthorityIssuerService.isAuthorityIssuer. - */ - @Test - public void testIsAuthorityIssuer() throws Exception { - - String weId = "did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"; - - ResponseData response = authorityIssuerService.isAuthorityIssuer(weId); - BeanUtil.print(response); - } - - /** - * test AuthorityIssuerService.queryAuthorityIssuerInfo. - */ - @Test - public void testQueryAuthorityIssuerInfo() throws Exception { - - String weId = "did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"; - - ResponseData response = - authorityIssuerService.queryAuthorityIssuerInfo(weId); - BeanUtil.print(response); - } -} diff --git a/src/test/java/com/webank/weid/service/TestCptService.java b/src/test/java/com/webank/weid/service/TestCptService.java deleted file mode 100644 index 25093665..00000000 --- a/src/test/java/com/webank/weid/service/TestCptService.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.service; - -import com.webank.weid.BaseTest; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.protocol.base.Cpt; -import com.webank.weid.protocol.base.CptBaseInfo; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.RegisterCptArgs; -import com.webank.weid.protocol.request.UpdateCptArgs; -import com.webank.weid.protocol.response.ResponseData; -import org.junit.Test; - -/** - * test CptService. - * - * @author v_wbgyang - */ -public class TestCptService extends BaseTest { - - /**jsonSchema for register.*/ - private static String schema = - "{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"/etc/fstab\",\"description\":\"JSON representation of /etc/fstab\",\"type\":\"object\",\"properties\":{\"swap\":{\"$ref\":\"#/definitions/mntent\"}},\"patternProperties\":{\"^/([^/]+(/[^/]+)*)?$\":{\"$ref\":\"#/definitions/mntent\"}},\"required\":[\"/\",\"swap\"],\"additionalProperties\":false,\"definitions\":{\"mntent\":{\"title\":\"mntent\",\"description\":\"An fstab entry\",\"type\":\"object\",\"properties\":{\"device\":{\"type\":\"string\"},\"fstype\":{\"type\":\"string\"},\"options\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"string\"}},\"dump\":{\"type\":\"integer\",\"minimum\":0},\"fsck\":{\"type\":\"integer\",\"minimum\":0}},\"required\":[\"device\",\"fstype\"],\"additionalItems\":false}}}"; - - /** - * test CptService.registerCpt. - */ - @Test - public void testRegisterCpt() throws Exception { - - RegisterCptArgs registerCptArgs = new RegisterCptArgs(); - registerCptArgs.setCptPublisherPrivateKey(new WeIdPrivateKey()); - registerCptArgs.getCptPublisherPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - registerCptArgs.setCptJsonSchema(schema); - registerCptArgs.setCptPublisher("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - - ResponseData response = cptService.registerCpt(registerCptArgs); - BeanUtil.print(response); - } - - /** - * test CptService.queryCpt. - */ - @Test - public void testQueryCpt() throws Exception { - - Integer cptId = new Integer(2000682); - - ResponseData response = cptService.queryCpt(cptId); - BeanUtil.print(response); - } - - /** - * test CptService.updateCpt. - */ - @Test - public void testUpdateCpt() throws Exception { - - UpdateCptArgs updateCptArgs = new UpdateCptArgs(); - updateCptArgs.setCptPublisherPrivateKey(new WeIdPrivateKey()); - updateCptArgs.getCptPublisherPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - updateCptArgs.setCptJsonSchema(schema); - updateCptArgs.setCptPublisher("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - Integer cptId = new Integer(2000682); - updateCptArgs.setCptId(cptId); - - ResponseData response = cptService.updateCpt(updateCptArgs); - BeanUtil.print(response); - } -} diff --git a/src/test/java/com/webank/weid/service/TestCredentialService.java b/src/test/java/com/webank/weid/service/TestCredentialService.java deleted file mode 100644 index 446319b6..00000000 --- a/src/test/java/com/webank/weid/service/TestCredentialService.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.service; - -import com.webank.weid.BaseTest; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.base.WeIdPublicKey; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; -import com.webank.weid.protocol.response.ResponseData; -import com.webank.weid.util.DateUtils; -import java.text.ParseException; -import org.junit.Test; - -/** - * test CredentialService. - * - * @author v_wbgyang - */ -public class TestCredentialService extends BaseTest { - - /**claimData for register.*/ - private static String schemaData = - "{\"/\":{\"device\":\"/dev/sda1\",\"fstype\":\"btrfs\",\"options\":[\"ssd\"]},\"swap\":{\"device\":\"/dev/sda2\",\"fstype\":\"swap\"},\"/tmp\":{\"device\":\"tmpfs\",\"fstype\":\"tmpfs\",\"options\":[\"size=64M\"]},\"/var/lib/mysql\":{\"device\":\"/dev/data/mysql\",\"fstype\":\"btrfs\"}}"; - - /** - * test CredentialService.createCredential. - */ - @Test - public void testcreateCredential() throws Exception { - - CreateCredentialArgs createCredentialArgs = buildCreateCredentialArgs(); - - ResponseData response = - credentialService.createCredential(createCredentialArgs); - BeanUtil.print(response); - } - - /** - * test CredentialService.verifyCredential. - */ - @Test - public void testVerifyCredential() throws Exception { - - CreateCredentialArgs createCredentialArgs = buildCreateCredentialArgs(); - ResponseData ctresponse = - credentialService.createCredential(createCredentialArgs); - - ResponseData response = credentialService.verifyCredential(ctresponse.getResult()); - BeanUtil.print(response); - } - - /** - * test CredentialService.verifyCredentialWithSpecifiedPubKey. - */ - @Test - public void testVerifyCredentialWithPublicKey() throws Exception { - - CreateCredentialArgs createCredentialArgs = buildCreateCredentialArgs(); - ResponseData ctresponse = - credentialService.createCredential(createCredentialArgs); - - VerifyCredentialArgs verifyCredentialArgs = new VerifyCredentialArgs(); - verifyCredentialArgs.setWeIdPublicKey(new WeIdPublicKey()); - verifyCredentialArgs.getWeIdPublicKey().setPublicKey( - "13018259646160420136476747261062739427107399118741098594421740627408250832097563679915569899249860162658726497802275511046279230970892819141376414047446393"); - - verifyCredentialArgs.setCredential(ctresponse.getResult()); - - ResponseData response = - credentialService.verifyCredentialWithSpecifiedPubKey(verifyCredentialArgs); - BeanUtil.print(response); - } - - /** - * buildCreateCredentialArgs. - * - * @return CreateCredentialArgs CreateCredentialArgs Object - * @throws ParseException may be throw ParseException - */ - private CreateCredentialArgs buildCreateCredentialArgs() throws ParseException { - - CreateCredentialArgs createCredentialArgs = new CreateCredentialArgs(); - createCredentialArgs.setWeIdPrivateKey(new WeIdPrivateKey()); - createCredentialArgs.getWeIdPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - createCredentialArgs.setClaim(schemaData); - createCredentialArgs.setCptId(2000682); - createCredentialArgs - .setExpirationDate(DateUtils.convertStringToDate("2019-10-11T18:09:42Z").getTime()); - createCredentialArgs.setIssuer("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db1"); - - return createCredentialArgs; - } -} diff --git a/src/test/java/com/webank/weid/service/TestWeIdService.java b/src/test/java/com/webank/weid/service/TestWeIdService.java deleted file mode 100644 index c40cc018..00000000 --- a/src/test/java/com/webank/weid/service/TestWeIdService.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ - -package com.webank.weid.service; - -import com.webank.weid.BaseTest; -import com.webank.weid.common.BeanUtil; -import com.webank.weid.protocol.base.WeIdDocument; -import com.webank.weid.protocol.base.WeIdPrivateKey; -import com.webank.weid.protocol.request.CreateWeIdArgs; -import com.webank.weid.protocol.request.SetAuthenticationArgs; -import com.webank.weid.protocol.request.SetPublicKeyArgs; -import com.webank.weid.protocol.request.SetServiceArgs; -import com.webank.weid.protocol.response.CreateWeIdDataResult; -import com.webank.weid.protocol.response.ResponseData; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Keys; -import org.junit.Test; - -/** - * test service. - * - * @author v_wbgyang - */ -public class TestWeIdService extends BaseTest { - - /** - * you can get the publicKey and privateKey after testGenerateKeyPair. - */ - @Test - public void testGenerateKeyPair() throws Exception { - - ECKeyPair keyPair = Keys.createEcKeyPair(); - String publicKey = String.valueOf(keyPair.getPublicKey()); - String privateKey = String.valueOf(keyPair.getPrivateKey()); - System.out.println("publicKey:" + publicKey); - System.out.println("privateKey:" + privateKey); - } - - /** - * test without reference method createWeId can't assert the result, because it is random. - */ - @Test - public void testCreateWeId_() throws Exception { - - ResponseData response = weIdService.createWeId(); - BeanUtil.print(response); - } - - /** - * test a parameter method createWeId. - */ - @Test - public void testCreateWeId() throws Exception { - - CreateWeIdArgs args = new CreateWeIdArgs(); - args.setWeIdPrivateKey(new WeIdPrivateKey()); - args.getWeIdPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - args.setPublicKey( - "13018259646160420136476747261062739427107399118741098594421740627408250832097563679915569899249860162658726497802275511046279230970892819141376414047446393"); - - ResponseData response = weIdService.createWeId(args); - BeanUtil.print(response); - } - - /** - * test WeIdService.testGetWeIdDocumentJson. - */ - @Test - public void testGetWeIdDocumentJson() throws Exception { - - String weId = "did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db1"; - - ResponseData response = weIdService.getWeIdDocumentJson(weId); - BeanUtil.print(response); - } - - /** - * test WeIdService.getWeIdDocument. - */ - @Test - public void testGetWeIdDocument() throws Exception { - - System.out.println("currentBlockNumber:" + this.getBlockNumber()); - String weId = "did:weid:0x0518f2b92fad9da7807a78b58af64db8997357d1"; - ResponseData isExists = weIdService.isWeIdExist(weId); - System.out.println("is exists:" + isExists.getResult()); - - long startTime = System.currentTimeMillis(); - ResponseData response = weIdService.getWeIdDocument(weId); - System.out.println("gas time:" + (System.currentTimeMillis() - startTime)); - BeanUtil.print(response); - } - - /** - * test WeIdService.setPublicKey. - */ - @Test - public void testSetPublicKey() throws Exception { - - SetPublicKeyArgs setPublicKeyArgs = new SetPublicKeyArgs(); - setPublicKeyArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setPublicKeyArgs.getUserWeIdPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - setPublicKeyArgs.setWeId("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - setPublicKeyArgs.setOwner("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - setPublicKeyArgs.setType("Secp256k1"); - setPublicKeyArgs.setPublicKey( - "13018259646160420136476747261062739427107399118741098594421740627408250832097563679915569899249860162658726497802275511046279230970892819141376414047446393"); - - ResponseData response = weIdService.setPublicKey(setPublicKeyArgs); - BeanUtil.print(response); - } - - /** - * test WeIdService.setService. - */ - @Test - public void testSetService() throws Exception { - - SetServiceArgs setServiceArgs = new SetServiceArgs(); - setServiceArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setServiceArgs.getUserWeIdPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - setServiceArgs.setWeId("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - setServiceArgs.setType("drivingCardService"); - setServiceArgs.setServiceEndpoint("https://weidentity.webank.com/endpoint/8377464"); - - ResponseData response = weIdService.setService(setServiceArgs); - BeanUtil.print(response); - } - - /** - * test WeIdService.setAuthenticate. - */ - @Test - public void testSetAuthentication() throws Exception { - - SetAuthenticationArgs setAuthenticationArgs = new SetAuthenticationArgs(); - setAuthenticationArgs.setUserWeIdPrivateKey(new WeIdPrivateKey()); - setAuthenticationArgs.getUserWeIdPrivateKey().setPrivateKey( - "38847998560426504802666437193681088212587743543930619195304160132018773764799"); - - setAuthenticationArgs.setWeId("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - setAuthenticationArgs.setOwner("did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"); - setAuthenticationArgs.setPublicKey( - "13018259646160420136476747261062739427107399118741098594421740627408250832097563679915569899249860162658726497802275511046279230970892819141376414047446393"); - setAuthenticationArgs.setType("RsaSignatureAuthentication2018"); - - ResponseData response = weIdService.setAuthentication(setAuthenticationArgs); - BeanUtil.print(response); - } - - /** - * test WeIdService.isWeIdExist. - */ - @Test - public void testIsWeIdExist() throws Exception { - - String weId = "did:weid:0x0518f2b92fad9da7807a78b58af64db8997357db"; - - ResponseData response = weIdService.isWeIdExist(weId); - BeanUtil.print(response); - } -} diff --git a/src/test/java/com/webank/weid/util/TestBeanUtil.java b/src/test/java/com/webank/weid/util/TestBeanUtil.java new file mode 100644 index 00000000..d6e8077a --- /dev/null +++ b/src/test/java/com/webank/weid/util/TestBeanUtil.java @@ -0,0 +1,80 @@ + + +package com.webank.weid.util; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.BeanUtil; +import com.webank.weid.common.PasswordKey; +import com.webank.weid.blockchain.constant.ErrorCode; +import com.webank.weid.blockchain.protocol.response.ResponseData; + +/** + * test for BeanUtil. + * + * @author v_wbgyang + */ +public class TestBeanUtil { + + private static final Logger logger = LoggerFactory.getLogger(TestBeanUtil.class); + + @Test + public void testPrint() { + + logger.info(BeanUtil.objToString(null)); + + PasswordKey passwordKey = new PasswordKey(); + passwordKey.setPrivateKey("123"); + + logger.info(BeanUtil.objToString(passwordKey)); + logger.info( + BeanUtil.objToString(new ResponseData(passwordKey, ErrorCode.SUCCESS)) + ); + + Map map = new HashMap(); + map.put("key1", passwordKey); + map.put("key2", "1234"); + map.put("key3", new Date()); + + logger.info(BeanUtil.objToString(map)); + logger.info(BeanUtil.objToString(new String[]{"one", "two"})); + logger.info(BeanUtil.objToString(new Date())); + logger.info(BeanUtil.objToString(new BigDecimal(23))); + logger.info(BeanUtil.objToString(new BigInteger("11"))); + + List list = new ArrayList(); + list.add(1); + list.add(passwordKey); + list.add(new Date()); + list.add(null); + + logger.info(BeanUtil.objToString(list)); + logger.info(BeanUtil.objToString(new ResponseData>(list, ErrorCode.SUCCESS))); + + map.put("list", list); + map.put("response", new ResponseData>(list, ErrorCode.SUCCESS)); + logger.info(BeanUtil.objToString(map)); + + Map newMap = new HashMap(); + newMap.put("map", map); + logger.info(BeanUtil.objToString(newMap)); + + List newList = new ArrayList(); + newList.add(list); + newList.add(newMap); + newList.add(null); + logger.info(BeanUtil.objToString(newList)); + Assert.assertTrue(true); + } +} \ No newline at end of file diff --git a/src/test/java/com/webank/weid/util/TestBuildPrivateKey.java b/src/test/java/com/webank/weid/util/TestBuildPrivateKey.java index 99f33594..cabf8c29 100644 --- a/src/test/java/com/webank/weid/util/TestBuildPrivateKey.java +++ b/src/test/java/com/webank/weid/util/TestBuildPrivateKey.java @@ -1,45 +1,35 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import com.webank.weid.full.TestBaseUtil; import java.math.BigInteger; -import org.junit.Test; + +import org.junit.Assert; +import org.junit.Ignore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.webank.weid.common.PasswordKey; +import com.webank.weid.full.TestBaseUtil; /** - * the role of this class is to handle the private key required - * in the testing process. - * - * @author v_wbgyang + * the role of this class is to handle the private key required in the testing process. * + * @author v_wbgyang */ public class TestBuildPrivateKey { - /** - * extract the private key in org1.txt and transform it into 16 binary system + private static final Logger logger = LoggerFactory.getLogger(TestBuildPrivateKey.class); + + /** + * extract the private key in org1.txt and transform it into 16 binary system */ - @Test + @Ignore public void testBuildPrivateKey() { - String[] pk = TestBaseUtil.resolvePk("org1.txt"); - BigInteger bigInter1 = new BigInteger(pk[1], 10); + PasswordKey passwordKey = TestBaseUtil.resolvePk("org1.txt"); + BigInteger bigInter1 = new BigInteger(passwordKey.getPrivateKey(), 10); String str1 = bigInter1.toString(16); - System.out.println("\nprivate key:" + str1); + logger.info("private key:{}", str1); + Assert.assertNotNull(str1); } } diff --git a/src/test/java/com/webank/weid/util/TestCredentialUtils.java b/src/test/java/com/webank/weid/util/TestCredentialUtils.java index a129c019..e9ff7e66 100644 --- a/src/test/java/com/webank/weid/util/TestCredentialUtils.java +++ b/src/test/java/com/webank/weid/util/TestCredentialUtils.java @@ -1,40 +1,26 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import com.webank.weid.protocol.base.Credential; -import com.webank.weid.protocol.request.CreateCredentialArgs; -import com.webank.weid.protocol.request.VerifyCredentialArgs; -import com.webank.weid.util.CredentialUtils; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import com.webank.weid.constant.CredentialConstant.CredentialProofType; +import com.webank.weid.constant.ErrorCode; +import com.webank.weid.constant.ParamKeyConstant; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.request.CreateCredentialArgs; /** * test crentialUtils. - * - * @author v_wbjnzhang * + * @author v_wbjnzhang */ public class TestCredentialUtils { @@ -42,49 +28,60 @@ public class TestCredentialUtils { public void getCredentialFieldsTest() { // test arg is null - Credential arg = null; - String result = CredentialUtils.getCredentialFields(arg); - assertEquals(result, ""); - } - - @Test - public void extractCredentialResultTest() { - VerifyCredentialArgs args = null; - Credential result = CredentialUtils.extractCredentialResult(args); - assertNull(result); - - Credential arg = new Credential(); - arg.setContext(CredentialUtils.getDefaultCredentialContext()); - arg.setId(UUID.randomUUID().toString()); - arg.setCptId(14356); - arg.setIssuer("gdsgshher"); - arg.setIssuranceDate(new Long(System.currentTimeMillis())); - arg.setExpirationDate(new Long(System.currentTimeMillis())); - arg.setClaim("sfsfs"); - args = new VerifyCredentialArgs(); - args.setCredential(arg); - result = CredentialUtils.extractCredentialResult(args); - assertNotNull(result); + Map map = new HashMap<>(); + String result = CredentialUtils.getCredentialThumbprintWithoutSig(null, map); + Assert.assertEquals(result, ""); } @Test public void extractCredentialMetadataTest() { - Credential arg = null; - CreateCredentialArgs result = CredentialUtils.extractCredentialMetadata(arg); - assertNull(result); - arg = new Credential(); + CreateCredentialArgs result = CredentialUtils.extractCredentialMetadata(null); + Assert.assertNull(result); + + Credential arg = new Credential(); result = CredentialUtils.extractCredentialMetadata(arg); - assertNotNull(result); + Assert.assertNotNull(result); arg.setContext(CredentialUtils.getDefaultCredentialContext()); arg.setId(UUID.randomUUID().toString()); arg.setCptId(14356); arg.setIssuer("gdsgshher"); - arg.setIssuranceDate(new Long(System.currentTimeMillis())); - arg.setExpirationDate(new Long(System.currentTimeMillis())); - arg.setClaim("sfsfs"); + arg.setExpirationDate(Long.valueOf(System.currentTimeMillis())); + arg.setIssuanceDate(Long.valueOf(System.currentTimeMillis())); + Assert.assertNotEquals(CredentialUtils.isCredentialValid(arg), ErrorCode.SUCCESS); + arg.setExpirationDate(Long.valueOf(System.currentTimeMillis()) + new Long(1000)); + arg.setIssuanceDate(Long.valueOf(System.currentTimeMillis())); + Assert.assertNotEquals(CredentialUtils.isCredentialValid(arg), ErrorCode.SUCCESS); + LinkedHashMap claim = new LinkedHashMap<>(); + claim.put("sfsfs", "sfsfs"); + claim.put("SampleAttrib", 10); + arg.setClaim(claim); + Map proof = new HashMap<>(); + proof.put(ParamKeyConstant.PROOF_CREATOR, arg.getIssuer()); + proof.put(ParamKeyConstant.PROOF_CREATED, arg.getIssuanceDate().toString()); + proof.put(ParamKeyConstant.PROOF_TYPE, CredentialProofType.ECDSA.getTypeName()); + proof.put(ParamKeyConstant.CREDENTIAL_SIGNATURE, "xxxxxxxxxxx"); + arg.setProof(proof); + String privateKey = + "58317564669857453586637110679746575832914889677346283755719850144028639639651"; + Assert.assertNotNull(CredentialUtils.getCredentialSignature(arg, privateKey, null)); + String fh = CredentialUtils.getFieldHash(arg); + Assert.assertNotNull(fh); result = CredentialUtils.extractCredentialMetadata(arg); - assertNotNull(result); + Assert.assertNotEquals(CredentialUtils.isCredentialValid(arg), ErrorCode.SUCCESS); + Assert.assertNotNull(CredentialUtils.isCreateCredentialArgsValid(result)); + Assert.assertTrue(CredentialUtils.isValidUuid(arg.getId())); + Assert.assertNotNull(CredentialUtils.convertCredentialIdToBytes32(arg.getId())); + Assert.assertNotNull(CredentialUtils.convertCredentialIdToBytes32(StringUtils.EMPTY)); + Assert.assertNotNull(CredentialUtils.extractCredentialMetadata(arg)); + Assert.assertNotNull(CredentialUtils.getClaimHash(arg, null)); + Assert.assertNotNull(result); + String thumbprint = CredentialUtils.getCredentialThumbprint(arg, null); + Assert.assertNotNull(thumbprint); + String thumbprintAll = CredentialUtils.getCredentialThumbprintWithoutSig(arg, null); + Assert.assertNotNull(thumbprintAll); + Credential test = CredentialUtils.copyCredential(arg); + Assert.assertTrue(CredentialUtils.isEqual(arg, test)); } } diff --git a/src/test/java/com/webank/weid/util/TestDataTypetUtils.java b/src/test/java/com/webank/weid/util/TestDataTypetUtils.java index e1871209..9b2e15ed 100644 --- a/src/test/java/com/webank/weid/util/TestDataTypetUtils.java +++ b/src/test/java/com/webank/weid/util/TestDataTypetUtils.java @@ -1,219 +1,232 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import org.bcos.web3j.abi.datatypes.DynamicArray; -import org.bcos.web3j.abi.datatypes.DynamicBytes; -import org.bcos.web3j.abi.datatypes.StaticArray; -import org.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.bcos.web3j.abi.datatypes.generated.Int256; -import org.bcos.web3j.abi.datatypes.generated.Uint256; -import org.bcos.web3j.abi.datatypes.generated.Uint8; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import org.fisco.bcos.sdk.abi.datatypes.DynamicArray; +import org.fisco.bcos.sdk.abi.datatypes.DynamicBytes; +import org.fisco.bcos.sdk.abi.datatypes.StaticArray; +import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32; +import org.fisco.bcos.sdk.abi.datatypes.generated.Int256; +import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256; +import org.fisco.bcos.sdk.abi.datatypes.generated.Uint8; + +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import com.webank.weid.constant.WeIdConstant; /** - * test DataTypetUtils. - * - * @author v_wbjnzhang + * test DataToolUtils. * + * @author v_wbjnzhang */ public class TestDataTypetUtils { + private static final Logger logger = LoggerFactory.getLogger(TestDataTypetUtils.class); + @Test public void testBytesArrayToBytes32() { byte[] bytes1 = new byte[32]; - Bytes32 result = DataTypetUtils.bytesArrayToBytes32(bytes1); - assertNotNull(result); + Bytes32 result = com.webank.weid.blockchain.util.DataToolUtils.bytesArrayToBytes32(bytes1); + Assert.assertNotNull(result); } @Test public void testStringToBytes32() { String str = "abcdefghijklmnopqrstuvwxyzABCDEF";// length is 32 - Bytes32 result = DataTypetUtils.stringToBytes32(str); - assertNotNull(result); + Bytes32 result = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + Assert.assertNotNull(result); } @Test public void testBytes32ToBytesArray() { String str = "abcdefghijklmnopqrstuvwxyzABCDEF"; - Bytes32 bytes32 = DataTypetUtils.stringToBytes32(str); - byte[] result = DataTypetUtils.bytes32ToBytesArray(bytes32); - assertNotNull(result); + Bytes32 bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + byte[] result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToBytesArray(bytes32); + Assert.assertNotNull(result); } @Test public void testBytes32ToString() { String str = "abcdefghijklmnopqrstuvwxyzABCDEF"; - Bytes32 bytes32 = DataTypetUtils.stringToBytes32(str); - String result = DataTypetUtils.bytes32ToString(bytes32); - assertEquals(result, str); + Bytes32 bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + String result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToString(bytes32); + Assert.assertEquals(result, str); str = ""; - bytes32 = DataTypetUtils.stringToBytes32(str); - result = DataTypetUtils.bytes32ToString(bytes32); - assertEquals(result, str); + bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToString(bytes32); + Assert.assertEquals(result, str); str = " slfjds ljlfs "; - bytes32 = DataTypetUtils.stringToBytes32(str); - result = DataTypetUtils.bytes32ToString(bytes32); - assertEquals(result, str.trim()); + bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToString(bytes32); + Assert.assertEquals(result, str.trim()); } @Test public void testBytes32ToStringWithoutTrim() { String str = "abcdefghijklmnopqrstuvwxyzABCDEF";// length is 32 - Bytes32 bytes32 = DataTypetUtils.stringToBytes32(str); - String result = DataTypetUtils.bytes32ToStringWithoutTrim(bytes32); - assertEquals(result, str); + Bytes32 bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + String result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToStringWithoutTrim(bytes32); + Assert.assertEquals(result, str); str = ""; - bytes32 = DataTypetUtils.stringToBytes32(str); - result = DataTypetUtils.bytes32ToStringWithoutTrim(bytes32); - assertEquals(result.length(), 32); + bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToStringWithoutTrim(bytes32); + Assert.assertEquals(result.length(), 32); str = " slfjds ljlfs "; - bytes32 = DataTypetUtils.stringToBytes32(str); - result = DataTypetUtils.bytes32ToStringWithoutTrim(bytes32); - assertEquals(result.length(), 32); + bytes32 = com.webank.weid.blockchain.util.DataToolUtils.stringToBytes32(str); + result = com.webank.weid.blockchain.util.DataToolUtils.bytes32ToStringWithoutTrim(bytes32); + Assert.assertEquals(result.length(), 32); } @Test public void testIntToUint256() { - + int n = 0; - Uint256 result = DataTypetUtils.intToUint256(n); - int m = DataTypetUtils.uint256ToInt(result); - assertEquals(n, m); + Uint256 result = com.webank.weid.blockchain.util.DataToolUtils.intToUint256(n); + int m = com.webank.weid.blockchain.util.DataToolUtils.uint256ToInt(result); + Assert.assertEquals(n, m); n = 9999999; - result = DataTypetUtils.intToUint256(n); - m = DataTypetUtils.uint256ToInt(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.intToUint256(n); + m = com.webank.weid.blockchain.util.DataToolUtils.uint256ToInt(result); + Assert.assertEquals(n, m); } @Test public void testIntToInt256() { - + int n = 0; - Int256 result = DataTypetUtils.intToInt256(n); - int m = DataTypetUtils.int256ToInt(result); - assertEquals(n, m); + Int256 result = com.webank.weid.blockchain.util.DataToolUtils.intToInt256(n); + int m = com.webank.weid.blockchain.util.DataToolUtils.int256ToInt(result); + Assert.assertEquals(n, m); n = 9999999; - result = DataTypetUtils.intToInt256(n); - m = DataTypetUtils.int256ToInt(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.intToInt256(n); + m = com.webank.weid.blockchain.util.DataToolUtils.int256ToInt(result); + Assert.assertEquals(n, m); n = -9999999; - result = DataTypetUtils.intToInt256(n); - m = DataTypetUtils.int256ToInt(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.intToInt256(n); + m = com.webank.weid.blockchain.util.DataToolUtils.int256ToInt(result); + Assert.assertEquals(n, m); } @Test public void testLongToInt256() { - + long n = 0L; - Int256 result = DataTypetUtils.longToInt256(n); - long m = DataTypetUtils.int256ToLong(result); - assertEquals(n, m); + Int256 result = com.webank.weid.blockchain.util.DataToolUtils.longToInt256(n); + long m = com.webank.weid.blockchain.util.DataToolUtils.int256ToLong(result); + Assert.assertEquals(n, m); n = 999999999999999L; - result = DataTypetUtils.longToInt256(n); - m = DataTypetUtils.int256ToLong(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.longToInt256(n); + m = com.webank.weid.blockchain.util.DataToolUtils.int256ToLong(result); + Assert.assertEquals(n, m); n = -999999999999999L; - result = DataTypetUtils.longToInt256(n); - m = DataTypetUtils.int256ToLong(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.longToInt256(n); + m = com.webank.weid.blockchain.util.DataToolUtils.int256ToLong(result); + Assert.assertEquals(n, m); } @Test public void testLongArrayToInt256StaticArray() { - + long[] array = {8L, 5555L, 64L, 0L, -147L}; - StaticArray result = DataTypetUtils.longArrayToInt256StaticArray(array); + StaticArray result = com.webank.weid.blockchain.util.DataToolUtils.longArrayToInt256StaticArray(array); DynamicArray result1 = new DynamicArray(result.getValue()); - long[] array1 = DataTypetUtils.int256DynamicArrayToLongArray(result1); + long[] array1 = com.webank.weid.blockchain.util.DataToolUtils.int256DynamicArrayToLongArray(result1); for (int i = 0; i < array.length; i++) { - assertEquals(array[i], array1[i]); + Assert.assertEquals(array[i], array1[i]); } } @Test public void teststringArrayToBytes32StaticArray() { - + String[] array = {"book", "student", "person", "apple"}; - StaticArray result = DataTypetUtils.stringArrayToBytes32StaticArray(array); + StaticArray result = com.webank.weid.blockchain.util.DataToolUtils.stringArrayToBytes32StaticArray(array); DynamicArray result1 = new DynamicArray(result.getValue()); - String[] array1 = DataTypetUtils.bytes32DynamicArrayToStringArrayWithoutTrim(result1); + String[] array1 = com.webank.weid.blockchain.util.DataToolUtils.bytes32DynamicArrayToStringArrayWithoutTrim(result1); for (int i = 0; i < array.length; i++) { - System.out.println("---" + array1[i] + "---"); + logger.info("---{}----", array1[i]); } + Assert.assertNotNull(array1); } @Test public void testIntToUint8() { int n = 0; - Uint8 result = DataTypetUtils.intToUnt8(n); - int m = DataTypetUtils.uint8ToInt(result); - assertEquals(n, m); + Uint8 result = com.webank.weid.blockchain.util.DataToolUtils.intToUnt8(n); + int m = com.webank.weid.blockchain.util.DataToolUtils.uint8ToInt(result); + Assert.assertEquals(n, m); n = 255; - result = DataTypetUtils.intToUnt8(n); - m = DataTypetUtils.uint8ToInt(result); - assertEquals(n, m); + result = com.webank.weid.blockchain.util.DataToolUtils.intToUnt8(n); + m = com.webank.weid.blockchain.util.DataToolUtils.uint8ToInt(result); + Assert.assertEquals(n, m); } @Test public void testStringToDynamicBytes() { String str = ""; - DynamicBytes result = DataTypetUtils.stringToDynamicBytes(str); - String newstr = DataTypetUtils.dynamicBytesToString(result); - assertEquals(str, newstr); + DynamicBytes result = com.webank.weid.blockchain.util.DataToolUtils.stringToDynamicBytes(str); + String newstr = com.webank.weid.blockchain.util.DataToolUtils.dynamicBytesToString(result); + Assert.assertEquals(str, newstr); str = "dssfdsgs"; - result = DataTypetUtils.stringToDynamicBytes(str); - newstr = DataTypetUtils.dynamicBytesToString(result); - assertEquals(str, newstr); + result = com.webank.weid.blockchain.util.DataToolUtils.stringToDynamicBytes(str); + newstr = com.webank.weid.blockchain.util.DataToolUtils.dynamicBytesToString(result); + Assert.assertEquals(str, newstr); str = " dssfdsdd gs "; - result = DataTypetUtils.stringToDynamicBytes(str); - newstr = DataTypetUtils.dynamicBytesToString(result); - assertEquals(str, newstr); + result = com.webank.weid.blockchain.util.DataToolUtils.stringToDynamicBytes(str); + newstr = com.webank.weid.blockchain.util.DataToolUtils.dynamicBytesToString(result); + Assert.assertEquals(str, newstr); str = "aaaaaaaaaabbbbbbbbbbccccccccccddaaaa"; - result = DataTypetUtils.stringToDynamicBytes(str); - newstr = DataTypetUtils.dynamicBytesToString(result); - assertEquals(str, newstr); + result = com.webank.weid.blockchain.util.DataToolUtils.stringToDynamicBytes(str); + newstr = com.webank.weid.blockchain.util.DataToolUtils.dynamicBytesToString(result); + Assert.assertEquals(str, newstr); + } + + @Test + public void testHashConversion() { + String hash = com.webank.weid.blockchain.util.DataToolUtils.hash(UUID.randomUUID().toString()); + logger.info("hash {}", hash); + byte[] convertedHash = com.webank.weid.blockchain.util.DataToolUtils.convertHashStrIntoHashByte32Array(hash); + Assert.assertEquals(convertedHash.length, WeIdConstant.BYTES32_FIXED_LENGTH.intValue()); + String convertedBackStr = com.webank.weid.blockchain.util.DataToolUtils + .convertHashByte32ArrayIntoHashStr(convertedHash); + Assert.assertEquals(hash, convertedBackStr); + Assert.assertEquals(hash.length(), WeIdConstant.BYTES32_FIXED_LENGTH * 2 + 2); + List listX = new ArrayList( + Arrays.asList("a", "b", "c", "d", "f", "f", "g")); + List listY = new ArrayList(Arrays.asList("a", "c", "f", "f", "g")); + List result = DataToolUtils.strictCheckExistence(listX, listY); + Assert.assertTrue(result.get(0) && result.get(2)); + Assert.assertFalse(result.get(1) || result.get(3)); + Assert.assertEquals(result.size(), 7); } } diff --git a/src/test/java/com/webank/weid/util/TestDateUtils.java b/src/test/java/com/webank/weid/util/TestDateUtils.java index 8c0a8cbd..e99e0762 100644 --- a/src/test/java/com/webank/weid/util/TestDateUtils.java +++ b/src/test/java/com/webank/weid/util/TestDateUtils.java @@ -1,24 +1,104 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import org.fisco.bcos.sdk.abi.datatypes.generated.Int256; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * test DateUtils. + * + * @author v_wbgyang + */ public class TestDateUtils { + private DateFormat df; + + private Date now; + + private SimpleDateFormat simpleDateFormat; + + /** + * initialization before test. + */ + @Before + public void init() { + TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); + df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + df.setTimeZone(tz); + + now = new Date(); + + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + } + + @Test + public void testGetIso8601Timestamp() { + + String dateString = DateUtils.getTimestamp(now); + Assert.assertEquals(df.format(now), dateString); + + dateString = DateUtils.getTimestamp(now.getTime()); + Assert.assertEquals(df.format(now), dateString); + } + + @Test + public void testConvertStringToDate() throws ParseException { + + String dateString = DateUtils.getTimestamp(now); + Date date = DateUtils.convertStringToDate(dateString); + Assert.assertEquals(DateUtils.getTimestamp(date), dateString); + + dateString = DateUtils.getTimestamp(now); + date = DateUtils.convertLongStringToDate(String.valueOf(now.getTime())); + Assert.assertEquals(DateUtils.getTimestamp(date), dateString); + } + + @Test + public void testConverDateToTimeStamp() throws ParseException { + + String dateString = "2018-12-20 11:35:43"; + long time = DateUtils.converDateToTimeStamp(dateString); + Assert.assertEquals(simpleDateFormat.parse(dateString).getTime(), time); + } + + @Test + public void testIsValidUtcDateString() { + + String dateString = DateUtils.getTimestamp(now); + boolean isValid = DateUtils.isValidDateString(dateString); + Assert.assertTrue(isValid); + + isValid = DateUtils.isValidDateString("2018-12-20 11:40:06"); + Assert.assertFalse(isValid); + } + + @Test + public void testGetCurrentTimeStampInt256() { + + Int256 int256String = DateUtils.getCurrentTimeStampInt256(); + Assert.assertNotNull(int256String); + + String timeStampString = DateUtils.getCurrentTimeStampString(); + Assert.assertNotNull(timeStampString); + + Long timestamp = DateUtils.getCurrentTimeStamp(); + Assert.assertNotNull(timestamp); + } + + @Test + public void testConvertUtcDate() throws Exception { + String testDate = "2019-03-19T21:12:33Z"; + Long testLongDate = DateUtils.convertUtcDateToTimeStamp(testDate); + Assert.assertNotNull(testLongDate); + } } diff --git a/src/test/java/com/webank/weid/util/TestHashUtils.java b/src/test/java/com/webank/weid/util/TestHashUtils.java index a1e04b65..f6d9cc97 100644 --- a/src/test/java/com/webank/weid/util/TestHashUtils.java +++ b/src/test/java/com/webank/weid/util/TestHashUtils.java @@ -1,44 +1,44 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; +import java.nio.charset.StandardCharsets; + +import org.fisco.bcos.sdk.crypto.CryptoSuite; +import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * test HashUtils. - * - * @author v_wbjnzhang * + * @author v_wbjnzhang */ public class TestHashUtils { + private static final Logger logger = LoggerFactory.getLogger(TestHashUtils.class); + @Test - public void testHashUtils() throws Exception { - + public void testHashUtils() { + String rawString = "hello world."; - byte[] rawBytes = rawString.getBytes(); - System.out.println("String: " + rawString + ", Bytes: " + new String(rawBytes)); - String hashedString = HashUtils.sha3(rawString); - byte[] hashedBytes = HashUtils.sha3(rawBytes); + byte[] rawBytes = rawString.getBytes(StandardCharsets.UTF_8); + logger.info("Befor hash, String: {}, Bytes: {} ", + rawString, + rawBytes, + new String(rawBytes, StandardCharsets.UTF_8) + ); + CryptoSuite cryptoSuite = new CryptoSuite(0); + String hashedString = cryptoSuite.hash(rawString); + byte[] hashedBytes = cryptoSuite.hash(rawBytes); // use assert here to verify the String to be 64 bit and Bytes[] to be // 32 bit - System.out.println("After hash, String: " + hashedString + ", Bytes: " + hashedBytes); + logger.info( + "After hash, String: {}, Bytes: {}", + hashedString, + new String(hashedBytes, StandardCharsets.UTF_8) + ); + Assert.assertNotNull(hashedBytes); } } diff --git a/src/test/java/com/webank/weid/util/TestJsonUtil.java b/src/test/java/com/webank/weid/util/TestJsonUtil.java new file mode 100644 index 00000000..427773f8 --- /dev/null +++ b/src/test/java/com/webank/weid/util/TestJsonUtil.java @@ -0,0 +1,90 @@ + + +package com.webank.weid.util; + +import com.networknt.schema.ValidationMessage; +import com.webank.weid.constant.CredentialConstant; +import com.webank.weid.constant.JsonSchemaConstant; +import com.webank.weid.protocol.base.Challenge; +import com.webank.weid.protocol.base.Credential; +import com.webank.weid.protocol.cpt.Cpt103; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Set; +import java.util.UUID; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +public class TestJsonUtil { + + @Test + public void testObjToJsonStr() { + + LinkedHashMap propertitesMap = new LinkedHashMap(); + propertitesMap.put(JsonSchemaConstant.TYPE_KEY, JsonSchemaConstant.DATA_TYPE_STRING); + propertitesMap.put(JsonSchemaConstant.DESCRIPTION_KEY, "this is name"); + + // String propertites = JsonUtil.objToJsonStr(propertitesMap); + String propertites = DataToolUtils.serialize(propertitesMap); + Assert.assertNotNull(propertites); + } + + @SuppressWarnings("unchecked") + @Test + public void testJsonStrToObj() { + + LinkedHashMap map = new LinkedHashMap<>(); + String s = "{\"name\":\"zhang san\", \"age\":21}"; + // LinkedHashMap propertitesMap = + // (LinkedHashMap)JsonUtil.jsonStrToObj(map, s); + LinkedHashMap propertitesMap = + DataToolUtils.deserialize(s, LinkedHashMap.class); + Assert.assertNotNull(propertitesMap); + } + + @Test + public void testMapConversion() throws Exception { + String uuid = UUID.randomUUID().toString(); + Credential cred = new Credential(); + cred.setIssuer("did:weid:0x00000011111111111"); + cred.setIssuanceDate(System.currentTimeMillis()); + cred.setExpirationDate(System.currentTimeMillis() + new Long(10000)); + cred.setContext(CredentialConstant.DEFAULT_CREDENTIAL_CONTEXT); + cred.setId(uuid); + cred.setCptId(55); + HashMap claim = new HashMap<>(); + claim.put("xxxxxxxxxxxxxx", "xxxxxxxxxxxxxx"); + claim.put("xxy", "yyx"); + claim.put("age", 12); + claim.put("acc", new BigInteger("111111111111111")); + claim.put("date", new Long(1000000000)); + cred.setClaim(claim); + String json = DataToolUtils.mapToCompactJson(DataToolUtils.objToMap(cred)); + Assert.assertFalse(StringUtils.isEmpty(json)); + Credential newcred = DataToolUtils.deserialize(json, Credential.class); + Assert.assertNotNull(newcred); + } + + @Test + public void testCptGenerator() throws Exception { + String cptSchema = DataToolUtils.generateDefaultCptJsonSchema(11); + Assert.assertTrue(DataToolUtils.isCptJsonSchemaValid(cptSchema)); + + cptSchema = DataToolUtils.generateDefaultCptJsonSchema(103); + Assert.assertTrue(DataToolUtils.isCptJsonSchemaValid(cptSchema)); + Cpt103 cpt103 = new Cpt103(); + cpt103.setChallenge(Challenge.create("did:weid:0x11111", "abcd")); + cpt103.setProof("aaa"); + cpt103.setId("did:weid:101:0x12221"); + Set checkRes = DataToolUtils.checkJsonVersusSchema( + DataToolUtils.objToJsonStrWithNoPretty(cpt103), cptSchema); + Assert.assertTrue(checkRes.size() == 0); + + cptSchema = DataToolUtils.generateDefaultCptJsonSchema(105); + Assert.assertTrue(DataToolUtils.isCptJsonSchemaValid(cptSchema)); + cptSchema = DataToolUtils.generateUnformattedCptJsonSchema(); + Assert.assertTrue(DataToolUtils.isCptJsonSchemaValid(cptSchema)); + } +} diff --git a/src/test/java/com/webank/weid/util/TestKeyStoreUtils.java b/src/test/java/com/webank/weid/util/TestKeyStoreUtils.java new file mode 100644 index 00000000..c4ea3d35 --- /dev/null +++ b/src/test/java/com/webank/weid/util/TestKeyStoreUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright© (2018-2020) WeBank Co., Ltd. + * + * This file is part of weid-java-sdk. + * + * weid-java-sdk is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * weid-java-sdk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with weid-java-sdk. If not, see . + */ + +package com.webank.weid.util; + +import com.webank.weid.util.keystore.P12KeyStore; +import com.webank.weid.util.keystore.PEMKeyStore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * + * @author tangxianjie + * @date 2022/09/11 + */ +public class TestKeyStoreUtils { + + private static final Logger logger = LoggerFactory.getLogger(TestKeyStoreUtils.class); + + @Test + public void testStorePem() throws Exception { + + PEMKeyStore.storeKeyPairWithPemFormat("0xed6fa6b25315ae63b9044a58989ce20c53a87b3c8bfb1b57f064adc42984f5f9", "storePem.pem", "secp256k1"); + } + + @Test + public void testStoreP12() { + P12KeyStore.storeKeyPairWithP12Format("0xb1fe02c4313e4dec3b489cd054e0e3f224b3ea8e33424f573f6122efa56c44ee","1234", + "storeP12.p12","secp256k1", "ECDSAWITHSHA1"); + } +} diff --git a/src/test/java/com/webank/weid/util/TestSchemaValidator.java b/src/test/java/com/webank/weid/util/TestSchemaValidator.java new file mode 100644 index 00000000..93ca3f05 --- /dev/null +++ b/src/test/java/com/webank/weid/util/TestSchemaValidator.java @@ -0,0 +1,74 @@ +/** + * Copyright 2014-2021 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.webank.weid.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.JsonSchemaFactory; +import com.networknt.schema.SpecVersion.VersionFlag; +import com.networknt.schema.ValidationMessage; +import com.webank.weid.protocol.cpt.RawCptSchema; +import java.io.File; +import java.io.IOException; +import java.util.Set; +import org.apache.http.util.Asserts; +import org.junit.Test; + +public class TestSchemaValidator { + + @Test + public void testValidator() throws JsonProcessingException { + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V4); + ObjectMapper mapper = new ObjectMapper(); + JsonSchema schema = factory.getSchema("{\"enum\":[1, 2, 3, 4],\"enumErrorCode\":\"Not in the list\"}"); + + JsonNode node = mapper.readTree("7"); + JsonNode node2 = mapper.readTree("3"); + + Set errors = schema.validate(node); + // 如果validate通过,则Set为1 + System.out.println(errors.size()); + System.out.println(errors.iterator().next().getCode()); + + // 如果validate通过,则Set为空 + Set errors2 = schema.validate(node2); + System.out.println(errors2.size()); + + } + + @Test + public void testLoadJson() throws IOException { + JsonNode jsonNodeResource =DataToolUtils.loadJsonObjectFromResource("policy.json"); + File file = new File("src/test/resources/policy.json"); + System.out.println(file.getAbsolutePath()); + JsonNode jsonNodeFile =DataToolUtils.loadJsonObjectFromFile(file); + + Asserts.notNull(jsonNodeResource, "read null"); + Asserts.notNull(jsonNodeFile, "read null"); + + } + + @Test + public void testCheckCptDefaultSchema() { + for (int i = 101; i <= 111; i++) { + System.out.println(RawCptSchema.getCptSchema(i)); + } + System.out.println(RawCptSchema.getCptSchema(11)); + + } + +} diff --git a/src/test/java/com/webank/weid/util/TestSignatureUtils.java b/src/test/java/com/webank/weid/util/TestSignatureUtils.java index 88370685..c5d6e862 100644 --- a/src/test/java/com/webank/weid/util/TestSignatureUtils.java +++ b/src/test/java/com/webank/weid/util/TestSignatureUtils.java @@ -1,68 +1,76 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import java.math.BigInteger; -import org.bcos.web3j.crypto.ECKeyPair; -import org.bcos.web3j.crypto.Sign; +import com.webank.weid.protocol.response.RsvSignature; +import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.crypto.signature.SignatureResult; +import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; -import static org.junit.Assert.assertTrue; /** * Test SignatureUtils. - * - * @author v_wbjnzhang * + * @author v_wbjnzhang and chaoxinhu */ public class TestSignatureUtils { - @Test - public void testSignatureUtils() throws Exception { + private static final Logger logger = LoggerFactory.getLogger(TestSignatureUtils.class); - ECKeyPair keyPair = SignatureUtils.createKeyPair(); - // public key - // 6005884739482598907019672016029935954035758996027051146272921018865015941269698926222431345309233458526942087465818124661687956402067203118790805113144306 - // private key - // 11695290896330592173013668505941497555094145434653626165899956696676058923570 - // serialize key - String str = "hello world...........................yes"; - Sign.SignatureData sigData = SignatureUtils.signMessage(str, keyPair); - BigInteger publicKey = SignatureUtils.signatureToPublicKey(str, sigData); - System.out.println("publicKey " + publicKey); + + @Test + public void testSignatureUtils() + throws Exception { String privateKey = "58317564669857453586637110679746575832914889677346283755719850144028639639651"; - Sign.SignatureData sigData2 = SignatureUtils.signMessage(str, privateKey); - publicKey = SignatureUtils.signatureToPublicKey(str, sigData2); - System.out.println("publicKey " + publicKey); + //CryptoKeyPair keyPair = com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.getKeyPairFactory().createKeyPair(new BigInteger(privateKey)); + //logger.info("publicKey:{} ", keyPair.getHexPublicKey()); + //BigInteger publicKey = DataToolUtils.publicKeyFromPrivate(new BigInteger(privateKey)); + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privateKey, 10)); + logger.info("publicKey:{} ", publicKey); - boolean result = SignatureUtils.verifySignature(str, sigData2, publicKey); - assertTrue(result); + /*ECKeyPair keyPair = TestBaseUtil.createKeyPair(); + keyPair = ECKeyPair.create(new BigInteger(privateKey)); + logger.info("publicKey:{} ", keyPair.getPublicKey()); + logger.info("privateKey:{}", keyPair.getPrivateKey());*/ + //CryptoKeyPair keyPair = DataToolUtils.createKeyPairFromPrivate(new BigInteger(privateKey)); + //logger.info("privateKey:{}", keyPair.getHexPrivateKey()); - publicKey = SignatureUtils.publicKeyFromPrivate(new BigInteger(privateKey)); - System.out.println("publicKey " + publicKey); + String str = "hello world...........................yes"; + //Sign.SignatureData sigData = DataToolUtils.secp256k1SignToSignature(str, keyPair); + //ECDSASignatureResult sigData = DataToolUtils.secp256k1SignToSignature(str, keyPair); + RsvSignature signatureResult = DataToolUtils.signToRsvSignature(str, privateKey); + //byte[] serialized = DataToolUtils.simpleSignatureSerialization(sigData); + //Sign.SignatureData newSigData = DataToolUtils.simpleSignatureDeserialization(serialized); + //ECDSASignatureResult newSigData = DataToolUtils.simpleSignatureDeserialization(serialized); + logger.info(DataToolUtils.SigBase64Serialization(signatureResult)); - keyPair = SignatureUtils.createKeyPairFromPrivate(new BigInteger(privateKey)); + /*Sign.SignatureData signatureData = DataToolUtils + .convertBase64StringToSignatureData(new String(Base64.encode(serialized)));*/ + /*ECDSASignatureResult signatureData = DataToolUtils + .convertBase64StringToSignatureData(new String(Base64.encodeBase64(serialized)));*/ + //logger.info(signatureData.toString()); + } + + @Test + public void testSecp256k1Signatures() { + String privKey = + "58317564669857453586637110679746575832914889677346283755719850144028639639651"; + String msg = "12345"; + String publicKey = DataToolUtils.publicKeyStrFromPrivate(new BigInteger(privKey, 10)); + /*SignatureResult signatureResult = com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.sign(com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.hash(msg), + com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.getKeyPairFactory().createKeyPair(new BigInteger(privKey))); + //注意cryptoSuite.verify只能接收hex形式的publicKey + Boolean a = com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.verify((new BigInteger(publicKey, 10)).toString(16), com.webank.weid.blockchain.service.fisco.CryptoFisco.cryptoSuite.hash(msg), signatureResult.convertToString());*/ - byte[] serialized = SignatureUtils.simpleSignatureSerialization(sigData); - Sign.SignatureData newSigData = SignatureUtils.simpleSignatureDeserialization(serialized); - System.out.println(newSigData); + String sig = DataToolUtils.SigBase64Serialization(DataToolUtils.signToRsvSignature(msg, privKey)); + BigInteger bigPublicKey = new BigInteger(publicKey, 10); + boolean result = DataToolUtils.verifySignature(msg, sig, bigPublicKey); + Assert.assertTrue(result); } } diff --git a/src/test/java/com/webank/weid/util/TestTimestampUtils.java b/src/test/java/com/webank/weid/util/TestTimestampUtils.java new file mode 100644 index 00000000..25fcd1b4 --- /dev/null +++ b/src/test/java/com/webank/weid/util/TestTimestampUtils.java @@ -0,0 +1,37 @@ + + +package com.webank.weid.util; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import com.webank.weid.protocol.response.timestamp.wesign.GetTimestampResponse; +import com.webank.weid.protocol.response.timestamp.wesign.VerifyTimestampResponse; + +public class TestTimestampUtils { + + @Test + public void integrationTestWeSign() + throws Exception { + if (StringUtils.isBlank(PropertyUtils.getProperty("wesign.accessTokenUrl"))) { + return; + } + String accessToken = TimestampUtils.getWeSignAccessToken(); + Assert.assertTrue(!StringUtils.isBlank(accessToken)); + String signTicket = TimestampUtils.getWeSignTicketString(accessToken); + Assert.assertTrue(!StringUtils.isBlank(signTicket)); + String nonce = TimestampUtils.generateNonce(32, 32).get(0); + Assert.assertTrue(!StringUtils.isBlank(nonce)); + String originalText = "Value to be signed."; + String hashValue = TimestampUtils.getWeSignHash(originalText); + Assert.assertEquals(hashValue.length(), 40); + String signParam = TimestampUtils.getWeSignParam(nonce, signTicket); + GetTimestampResponse getResp = TimestampUtils.getTimestamp(signTicket, nonce, hashValue); + Assert.assertEquals(getResp.getCode(), 0); + VerifyTimestampResponse verifyResp = TimestampUtils + .verifyTimestamp(signParam, nonce, hashValue, + getResp.getResult().getData().getB64TimeStamp()); + Assert.assertEquals(verifyResp.getCode(), 0); + } +} diff --git a/src/test/java/com/webank/weid/util/TestWeIdUtils.java b/src/test/java/com/webank/weid/util/TestWeIdUtils.java index bab35f64..50948614 100644 --- a/src/test/java/com/webank/weid/util/TestWeIdUtils.java +++ b/src/test/java/com/webank/weid/util/TestWeIdUtils.java @@ -1,111 +1,106 @@ -/* - * Copyright© (2018) WeBank Co., Ltd. - * - * This file is part of weidentity-java-sdk. - * - * weidentity-java-sdk is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * weidentity-java-sdk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with weidentity-java-sdk. If not, see . - */ + package com.webank.weid.util; -import com.webank.weid.protocol.base.WeIdPrivateKey; +import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import static org.junit.Assert.*; +import com.webank.weid.protocol.base.WeIdPrivateKey; /** * Test WeIdUtils. - * - * @author v_wbjnzhang * + * @author v_wbjnzhang */ public class TestWeIdUtils { + private static final Logger logger = LoggerFactory.getLogger(TestWeIdUtils.class); + @Test public void testConvertWeIdToAddress() { - String weid = null; - String address = WeIdUtils.convertWeIdToAddress(weid); - assertEquals(address, ""); - weid = "gdhgdrhrhjrersgfds"; + String address = WeIdUtils.convertWeIdToAddress(null); + Assert.assertEquals(address, ""); + + String weid = "gdhgdrhrhjrersgfds"; address = WeIdUtils.convertWeIdToAddress(weid); - assertEquals(address, ""); + Assert.assertEquals(address, ""); address = "0xce84646754976464646"; weid = WeIdUtils.convertAddressToWeId(address); - System.out.println(weid); + logger.info(weid); address = WeIdUtils.convertWeIdToAddress(weid); - System.out.println(address); + logger.info(address); } @Test public void testIsWeIdValid() { - String weid = null; - boolean result = WeIdUtils.isWeIdValid(weid); - assertFalse(result); - weid = "gdhgdrhrhjrersgfds"; + boolean result = WeIdUtils.isWeIdValid(null); + Assert.assertFalse(result); + + String weid = "gdhgdrhrhjrersgfds"; result = WeIdUtils.isWeIdValid(weid); - assertFalse(result); + Assert.assertFalse(result); weid = "gdhgdrhrhjrersgfds:ffsf"; result = WeIdUtils.isWeIdValid(weid); - assertFalse(result); + Assert.assertFalse(result); + + weid = "did:weid:0x123471623125358127679*"; + result = WeIdUtils.isWeIdValid(weid); + Assert.assertFalse(result); - weid = "did:weid:0xce84646754976464646"; + weid = "did:weid:0xbb1670306aedfaeb75cff9581c99e56ba4797431"; result = WeIdUtils.isWeIdValid(weid); - assertTrue(result); + Assert.assertTrue(result); } @Test public void testConvertPublicKeyToWeId() { String publicKey = - "4152630134607745313775653941373712642376482837388159007706431164834407808290456176569372213582021586381145279900416808342958821437075568109344613716670953"; - String weid = WeIdUtils.convertPublicKeyToWeId(publicKey); - System.out.println(weid); + "4152630134607745313775653941373712642376482837388159007706431164834407808290456176" + + "569372213582021586381145279900416808342958821437075568109344613716670953"; + String weId = WeIdUtils.convertPublicKeyToWeId(publicKey); + Assert.assertNotNull(weId); + logger.info(weId); } - @Test - public void testIsKeypairMatch() { - - String publicKey = - "4152630134607745313775653941373712642376482837388159007706431164834407808290456176569372213582021586381145279900416808342958821437075568109344613716670953"; - String privateKey = - "58317564669857453586637110679746575832914889677346283755719850144028639639651"; - boolean result = WeIdUtils.isKeypairMatch(privateKey, publicKey); - assertTrue(result); - - privateKey = "646467494548664"; - result = WeIdUtils.isKeypairMatch(privateKey, publicKey); - assertFalse(result); - } +// @Test +// public void testIsKeypairMatch() { +// +// String publicKey = +// /*"41526301346077453137756539413737126423764828373881590077064311648344078082904561" +// + "76569372213582021586381145279900416808342958821437075568109344613716670953";*/ +// "616487157832629935695248334732183001470968861496251911400081764434326377050103015" +// + "62844338994634470121084706056348088101890813246949904622670239758638712304"; +// String privateKey = +// //"58317564669857453586637110679746575832914889677346283755719850144028639639651"; +// "95190837481536383166137149464958960030030752301426973662112256567139589090597"; +// boolean result = WeIdUtils.isEcdsaKeypairMatch(privateKey, publicKey); +// Assert.assertTrue(result); +// +// privateKey = "646467494548664"; +// result = WeIdUtils.isEcdsaKeypairMatch(privateKey, publicKey); +// Assert.assertFalse(result); +// } @Test public void testIsPrivateKeyValid() { - String privateKey = "58317564669857453586637110679746575832914889677346283755719850144028639639651"; WeIdPrivateKey key = new WeIdPrivateKey(); boolean result = WeIdUtils.isPrivateKeyValid(key); - assertFalse(result); + Assert.assertFalse(result); key.setPrivateKey(privateKey); result = WeIdUtils.isPrivateKeyValid(key); - assertTrue(result); + Assert.assertTrue(result); result = WeIdUtils.isPrivateKeyValid(null); - assertFalse(result); + Assert.assertFalse(result); } } diff --git a/src/test/resources/.gitkeep b/src/test/resources/.gitkeep new file mode 100644 index 00000000..781e3835 --- /dev/null +++ b/src/test/resources/.gitkeep @@ -0,0 +1,3 @@ +# Ignore everything in this directory +* +# Except this file !.gitkeep \ No newline at end of file diff --git a/src/test/resources/ca.crt b/src/test/resources/ca.crt index 3b25e342..eb26670d 100644 --- a/src/test/resources/ca.crt +++ b/src/test/resources/ca.crt @@ -1,43 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIJAKzDiIgxxWh7MA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV -BAMMAkNOMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQH -DAhTaGVuemhlbjETMBEGA1UECgwKRklTQ08tQkNPUzEOMAwGA1UECwwFY2hhaW4w -HhcNMTgxMTIxMDQzMzEyWhcNMjgxMTE4MDQzMzEyWjBmMQswCQYDVQQDDAJDTjEL -MAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UEBwwIU2hlbnpo -ZW4xEzARBgNVBAoMCkZJU0NPLUJDT1MxDjAMBgNVBAsMBWNoYWluMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnE6h+e8IBVLAFUcbugBk6LkcET72rGXK -BAD5c/P28UmEs8OM3B4wAJ9hBeXXhazsVFRxjf5Z63opJj2u631JsU9+rEGYXgx4 -79qpmUY/p2IgNnU2kkU7mBlgUsGH5bT75OQZogEanefBwCp/O7spOwW009I5OrU8 -Feyp3i1nEwGC6rZpR8orSt0uKISopSfsl0THi9teHjxv5d86f0EvwFMqQr2WRt1s -QH5AnIvpCL0T0c5BuTyfogAhDQyUef4NF1BLdlSygSQU3ucqSDY2LkKH3eL30rEf -RYIwEOdUQ24mcA48z4vTWmvZ1aJnkS3WZ2LO4Kzp9S33X0hpsbISNQIDAQABo1Aw -TjAdBgNVHQ4EFgQUIvulUoewmh6dEgIE2pAWmxeZCs4wHwYDVR0jBBgwFoAUIvul -Uoewmh6dEgIE2pAWmxeZCs4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAS0op04lG+atcitBbnCN9f23RbQ8JtBgJwFLMtQROX5sPzH+Yl0x/wpkbzPRC -c5ieJjnW4TsCAJdpVr9jwRxVJbE081zKmnNzdUlm80z8IlFjQ8bLjnIHjPfyoSuS -TFiEc9tLpXOhDRC9gq+niEkMFrnEWjO6TPlmnfX7o2dX+O9pK+NEjWKKt7QX5WEv -Zw1/AL6y7yf3RaC9gsOprOTD9hxF5QE1X6NUCqsY7a9Xrnt3DNQT1zhx2VoeC5RQ -svwb1YZ+3nGxU+gydrOkfiuO15+D7bN4dT+0O2/NgKZTtwSdq6ac2AQWxDN4yrgJ -9R3Cf2FY+6Ul1CV1hkOM0Y/kOg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgIJAJr9xZen9UkUMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV -BAMMAkNOMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQH -DAhTaGVuemhlbjETMBEGA1UECgwKRklTQ08tQkNPUzEOMAwGA1UECwwFY2hhaW4w -HhcNMTgxMTIxMDQzMzEyWhcNMjgxMTE4MDQzMzEyWjBmMQswCQYDVQQDDAJDTjEL -MAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UEBwwIU2hlbnpo -ZW4xEzARBgNVBAoMCkZJU0NPLUJDT1MxDjAMBgNVBAsMBWFnZW50MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvn5UikSp0LXdNkQer0PjL64HKLgRzcit -eAePXCuFxlmE2eEsuzot9h+Ucvs8GsLF/hGl1dsjKLdgw5VUCSTq70gbYOPXyThv -hy1YXqq+0Up56INZTlYCH/UQT9y5hJGNDBI0OD21nxCmmvMF38vkjhkZ8dGUG6Bp -rerbztg3lnHPaZXKWsYuS9+bUjZotUdOSyBiRrqKZPWD4wd84pjtAuoK8NjGz8ng -K2/EywvhXVfAUgoje+ydzkG/I/OvCZ/LpeaImznuG+5wiESp1wFbrmFNk6k1mKn3 -4m89Gq3CvtRujaRjkPEimnXxmq2Y10C0w43V5WlXYmIJfFRzgryseQIDAQABoxAw -DjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAM0DWpfwvCWbbLGPKF -U8KPPQSIpQJuHOMNbqNqWatoKmKpf6PHL+26EzXQIn31q1y7X6evu47628kOT6Yl -Ph2a08IVubjLQF2ru3NuGAcFqaIIYk+y0h73G4VPWx4CkvHxqodEPUMxGkgs/Q8n -DygRuIKrsj/nVW+soHH5HhaWXLJukL1xDQT8uSVfLI5aQ9IiXQI0mlTk9CC4dOea -W7xmG1pk5qWQtGPOHMrhoFfo3iX+eR+FhFRU4BFKAaPWVZvjxUHokRm8JoAChvSQ -J2im11/thyvYwbxDV9ImnmGphvfkE4iHPmCINK1Ww7WJ29f+/kEN1FN3tgcs6TSk -ambD +MIIDQTCCAimgAwIBAgIJAIJEZzGo1hwvMA0GCSqGSIb3DQEBCwUAMDYxDzANBgNV +BAMMBmFnZW5jeTETMBEGA1UECgwKZmlzY28tYmNvczEOMAwGA1UECwwFY2hhaW4w +IBcNMjIwNzIwMTIxNDUzWhgPMjEyMjA2MjYxMjE0NTNaMDYxDzANBgNVBAMMBmFn +ZW5jeTETMBEGA1UECgwKZmlzY28tYmNvczEOMAwGA1UECwwFY2hhaW4wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCszn7/qtoAQbORyx/JQdmYkpKkMkT1 +hjQhS4XPZq9PyamqCxXHjTnk7iNlGysn+geTwCYg8azSbvWMNoVuOo+MHK21ob0D +vzI4gEtM+hear930BbMrg1+TQfp/rcKgE8kkBPT4/6rObzvId2tZob7RW/ij1n57 +c0uhHUbbf+lbqE26Gr/LiKkRUb4oB3c96KoST4kfb+Pt+WLFo3OS6/ecX2nQbBKc +tCBv+A4nv5ZKJFCcITDJi7ZMdQK2EjiedpV9PaeV/GAdViYfHAbp6CD9h2KFYQuA +fqBdQO2UgRhX6aHpXDLh2GxPHqTu8yAWSTCmqWVGPqjSn7mYgbvii04PAgMBAAGj +UDBOMB0GA1UdDgQWBBRu0frHn383VveyYgY/RF/uzjZy1zAfBgNVHSMEGDAWgBRu +0frHn383VveyYgY/RF/uzjZy1zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4IBAQA73AfFySC2hnUZS8peyFvMPS5OuMpv0b0VEHoWn0LDf6Mn9KBdT+CWWNaJ +0ecVR7RmbWMXkwzEq3xJHAztaJtrowMvPxNsraS2Wz1cA9Dwr2jKQruwIMdcYrKs +KoGVYZxD4JvYIAAVBXQ36FU/p3dtqaA2yzfIs7hbsYARDcjJyO2bTJADQcLQCn8e +emFZ57/rHPoa0XA/DupG0HDeGZPKkY4I+NglhYvGg2Fiy6FU+p4BmIaCqMjL93+u +QWaH67xMCnP8aTQOWiIn+5X0P05TMLR31i/knUI45+PhoKVhM4i/oskeekPpK3BF +t4CcsvNr+7Jvr2MeqpL/R2qN2n4g -----END CERTIFICATE----- diff --git a/src/test/resources/claim.json b/src/test/resources/claim.json new file mode 100644 index 00000000..0a27ca13 --- /dev/null +++ b/src/test/resources/claim.json @@ -0,0 +1,6 @@ +{ + "id": "did:weid:101:0xce618fb7fbacaf6398a0b4b78bf2dd942c8c49c7", + "name": "1", + "gender":"F", + "age":1 +} \ No newline at end of file diff --git a/src/test/resources/client.keystore b/src/test/resources/client.keystore deleted file mode 100644 index 8d202d93..00000000 Binary files a/src/test/resources/client.keystore and /dev/null differ diff --git a/src/test/resources/consumer_private_key.p12 b/src/test/resources/consumer_private_key.p12 new file mode 100644 index 00000000..f30f29c7 Binary files /dev/null and b/src/test/resources/consumer_private_key.p12 differ diff --git a/src/test/resources/consumer_public_key.pem b/src/test/resources/consumer_public_key.pem new file mode 100644 index 00000000..fcfb8acc --- /dev/null +++ b/src/test/resources/consumer_public_key.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvpEMM5l37k2izwbs+i+T3ydnqVRG7wXq +Cpnn1fEXZa0Vr1NWJ+8bE9UpY2ZdGWkl/uH3j/yWp3L+8LofDv0wug== +-----END PUBLIC KEY----- diff --git a/src/test/resources/default_cpt/Cpt101.json b/src/test/resources/default_cpt/Cpt101.json new file mode 100644 index 00000000..73382ff4 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt101.json @@ -0,0 +1 @@ +{"type":"object","description":"Authorize data between WeIDs via the exposed Service Endpoint","title":"Data Authorization Token","properties":{"duration":{"type":"integer","description":"Duration of Validity in seconds"},"fromWeId":{"type":"string","description":"Authorize from this WeID"},"resourceId":{"type":"string","description":"Authorized Resource ID"},"serviceUrl":{"type":"string","description":"Service Endpoint URL"},"toWeId":{"type":"string","description":"Authorize to this WeID"}},"required":["duration","fromWeId","resourceId","serviceUrl","toWeId"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt102.json b/src/test/resources/default_cpt/Cpt102.json new file mode 100644 index 00000000..264324c6 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt102.json @@ -0,0 +1 @@ +{"type":"object","$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt103.json b/src/test/resources/default_cpt/Cpt103.json new file mode 100644 index 00000000..aa5fa494 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt103.json @@ -0,0 +1 @@ +{"type":"object","description":"Answer to meet the challenge","title":"Authentication Answer","properties":{"challenge":{"type":"object","properties":{"nonce":{"type":"string"},"version":{"type":"integer"},"weId":{"type":"string"}},"description":"The challenge"},"id":{"type":"string","description":"The entity's weidentity did"},"proof":{"type":"string","description":"The proof"}},"required":["challenge","id","proof"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt104.json b/src/test/resources/default_cpt/Cpt104.json new file mode 100644 index 00000000..264324c6 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt104.json @@ -0,0 +1 @@ +{"type":"object","$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt105.json b/src/test/resources/default_cpt/Cpt105.json new file mode 100644 index 00000000..486e4d30 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt105.json @@ -0,0 +1 @@ +{"type":"object","description":"API Endpoint address disclosure","title":"API Endpoint","properties":{"argType":{"type":"array","items":{"type":"string"},"description":"Argument types in sequence"},"description":{"type":"string","description":"Description"},"endpointName":{"type":"string","description":"Endpoint name"},"hostport":{"type":"string","description":"Network host and port"},"id":{"type":"string","description":"Owner WeIdentity DID"},"version":{"type":"string","description":"API Version"}},"required":["argType","description","endpointName","hostport","id","version"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt106.json b/src/test/resources/default_cpt/Cpt106.json new file mode 100644 index 00000000..3730a3e6 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt106.json @@ -0,0 +1 @@ +{"type":"object","description":"Embedded Signature object for multi-sign","title":"Embedded Signature","properties":{"credentialList":{"type":"array","items":{"type":"object","properties":{"claim":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"context":{"type":"string"},"cptId":{"type":"integer"},"expirationDate":{"type":"integer"},"hash":{"type":"string"},"id":{"type":"string"},"issuanceDate":{"type":"integer"},"issuer":{"type":"string"},"proof":{"type":"object","properties":{"get":{"type":"string"},"orDefault":{"type":"string"},"isEmpty":{"type":"boolean"}}},"proofType":{"type":"string"},"signature":{"type":"string"},"signatureThumbprint":{"type":"string"}}},"description":"Original credential list to be signed"}},"required":["credentialList"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt107.json b/src/test/resources/default_cpt/Cpt107.json new file mode 100644 index 00000000..2591d447 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt107.json @@ -0,0 +1 @@ +{"type":"object","description":"Embedded Signature object for multi-sign","title":"Embedded Signature","properties":{"credentialList":{"type":"array","items":{"type":"object","properties":{"claim":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"context":{"type":"string"},"cptId":{"type":"integer"},"credentialType":{"enum":["ORIGINAL","ZKP","LITE1"],"type":"string"},"expirationDate":{"type":"integer"},"hash":{"type":"string"},"id":{"type":"string"},"issuanceDate":{"type":"integer"},"issuer":{"type":"string"},"proof":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"proofType":{"type":"string"},"salt":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"signature":{"type":"string"},"signatureThumbprint":{"type":"string"},"type":{"type":"array","items":{"type":"string"}},"valueFromProof":{"type":"object"}}},"description":"Original credential list to be signed"}},"required":["credentialList"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt108.json b/src/test/resources/default_cpt/Cpt108.json new file mode 100644 index 00000000..74787b5e --- /dev/null +++ b/src/test/resources/default_cpt/Cpt108.json @@ -0,0 +1 @@ +{"type":"object","description":"Trusted timestamping envelope","title":"Trusted Timestamping","properties":{"authoritySignature":{"type":"string","description":"Signature value from Authority"},"claimHash":{"type":"string","description":"Claim Hash"},"credentialList":{"type":"array","items":{"type":"object","properties":{"claim":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"context":{"type":"string"},"cptId":{"type":"integer"},"credentialType":{"enum":["ORIGINAL","ZKP","LITE1"],"type":"string"},"expirationDate":{"type":"integer"},"hash":{"type":"string"},"id":{"type":"string"},"issuanceDate":{"type":"integer"},"issuer":{"type":"string"},"proof":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"proofType":{"type":"string"},"salt":{"type":"object","properties":{"get":{"type":"object"},"orDefault":{"type":"object"},"isEmpty":{"type":"boolean"}}},"signature":{"type":"string"},"signatureThumbprint":{"type":"string"},"type":{"type":"array","items":{"type":"string"}},"valueFromProof":{"type":"object"}}},"description":"Original credential list to be signed"},"timestamp":{"type":"integer","description":"Timestamp"},"timestampAuthority":{"type":"string","description":"Timestamp Authority"}},"required":["authoritySignature","claimHash","credentialList","timestamp","timestampAuthority"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt109.json b/src/test/resources/default_cpt/Cpt109.json new file mode 100644 index 00000000..4657bdaf --- /dev/null +++ b/src/test/resources/default_cpt/Cpt109.json @@ -0,0 +1 @@ +{"type":"object","description":"Trusted Timestamp from authorized 3rd-party, or chain consensus","title":"Trusted Timestamp","properties":{"claimHash":{"type":"string"},"hashKey":{"type":"string"},"signatureList":{"type":"string"},"timestamp":{"type":"integer"}},"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt11.json b/src/test/resources/default_cpt/Cpt11.json new file mode 100644 index 00000000..dd236727 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt11.json @@ -0,0 +1 @@ +{"type":"object","description":"Reserved CPT 11","title":"test CPT","properties":{"cptId":{"type":"integer","description":"CPT ID","minimum":1},"gender":{"type":"string","description":"Gender","enum":["MALE","FEMALE"]},"tags":{"type":"array","items":{"type":"string"},"description":"Registered Tags","minItems":1},"userId":{"type":"string","description":"User ID"},"userName":{"type":"string","description":"User Name","maxLength":30}},"required":["cptId","gender","tags","userId","userName"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt110.json b/src/test/resources/default_cpt/Cpt110.json new file mode 100644 index 00000000..c5db63f7 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt110.json @@ -0,0 +1 @@ +{"type":"object","description":"Reserved CPT 110","title":"metadata CPT","properties":{"context":{"type":"string","description":"context"},"cptId":{"type":"integer","description":"CPT ID"},"credentialId":{"type":"string","description":"credential ID"},"expirationDate":{"type":"integer","description":"expirationDate"},"issuanceDate":{"type":"integer","description":"issuanceDate"},"issuer":{"type":"string","description":"issuer weid"}},"required":["context","cptId","credentialId","expirationDate","issuanceDate","issuer"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt111.json b/src/test/resources/default_cpt/Cpt111.json new file mode 100644 index 00000000..08054132 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt111.json @@ -0,0 +1 @@ +{"type":"object","description":"Reserved CPT 111","title":"User CPT","properties":{"cptId":{"type":"string","description":"CPT ID"},"credentialSignatureRequest":{"type":"string","description":"credential Signature Request","minimum":1},"userNonce":{"type":"string","description":"User Nonce"}},"required":["cptId","credentialSignatureRequest","userNonce"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/default_cpt/Cpt11Salt.json b/src/test/resources/default_cpt/Cpt11Salt.json new file mode 100644 index 00000000..0ff68dc6 --- /dev/null +++ b/src/test/resources/default_cpt/Cpt11Salt.json @@ -0,0 +1 @@ +{"type":"object","description":"Reserved CPT 11Salt","title":"test CPT","properties":{"cptId":{"type":"string","description":"CPT ID","minimum":1},"userId":{"type":"string","description":"User ID"},"userName":{"type":"string","description":"User Name","maxLength":30}},"required":["cptId","userId","userName"],"$schema":"http://json-schema.org/draft-04/schema#"} \ No newline at end of file diff --git a/src/test/resources/disclosure.json b/src/test/resources/disclosure.json new file mode 100644 index 00000000..301cfaa2 --- /dev/null +++ b/src/test/resources/disclosure.json @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": 1, + "gender": 0, + "age":1 +} \ No newline at end of file diff --git a/src/test/resources/endpoint-data.properties b/src/test/resources/endpoint-data.properties new file mode 100644 index 00000000..e69de29b diff --git a/src/test/resources/fisco.properties.tpl b/src/test/resources/fisco.properties.tpl new file mode 100644 index 00000000..d0461228 --- /dev/null +++ b/src/test/resources/fisco.properties.tpl @@ -0,0 +1,65 @@ +# Fisco-bcos blockchain node related properties + +####################################################################################################### +# # +# fisco bcos version config # +# # +####################################################################################################### +# Version +bcos.version=${FISCO_BCOS_VERSION} + + +####################################################################################################### +# # +# contract address config # +# # +####################################################################################################### +# contract address +weId.contractaddress= +cpt.contractaddress= +issuer.contractaddress= +evidence.contractaddress= +specificissuer.contractaddress= + +# This variable is used to distinguish the environment. You can use "dev" to set the development environment, +# "stg" to set the test environment, "prd" to set the production environment, +# If you do not set it, the system will use allOrg as the environment by default. +# It is not recommended. Production use default configuration +cns.profile.active=${CNS_PROFILE_ACTIVE} + +####################################################################################################### +# # +# web3sdk connection config # +# # +####################################################################################################### +# blockchain connection params +web3sdk.timeout=30 +web3sdk.core-pool-size=100 +web3sdk.max-pool-size=200 +web3sdk.queue-capacity=1000 +web3sdk.keep-alive-seconds=60 + + +####################################################################################################### +# # +# fisco bcos 2.0 related config # +# # +####################################################################################################### +# Fisco-Bcos 2.x params, including Group ID and Encrypt Type +group.id=1 + +####################################################################################################### +# # +# fisco bcos node cert related config # +# # +####################################################################################################### +# Fisco-Bcos sdk SSL encrypt type, false:ECDSA, true:SM2 +sdk.sm-crypto=false +# fisco-bcos sdk cert path contains[ca.crt,sdk.crt,sdk.key] +# if sdk.sm-crypto is true, contains [gm] directory, and gm dir contains [gmca.crt,gmsdk.crt,gmsdk.key,gmensdk.crt,gmensdk.key] +sdk.cert-path=resources/conf + +# amop public key of pem and private key of p12 configuration +amop.pub-path=resources/conf/amop/consumer_public_key.pem +amop.pri-path=resources/conf/amop/consumer_private_key.p12 +amop.p12-password=123456 \ No newline at end of file diff --git a/src/test/resources/gm/gmca.crt b/src/test/resources/gm/gmca.crt new file mode 100644 index 00000000..5f85b87f --- /dev/null +++ b/src/test/resources/gm/gmca.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBxDCCAWqgAwIBAgIJAIK0FHy8gSBHMAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM +B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX +DTIyMDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjA3MRAwDgYDVQQDDAdnbWNo +YWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjBZMBMGByqG +SM49AgEGCCqBHM9VAYItA0IABPzo9TYTFPRUcy4RealZ80US9iKtPDbMb+cVL0TE +TvVj+Pg6Pr0T2Rstib4jyBYDYnzko8RrPTNy5Fo/XnYbzpmjXTBbMB0GA1UdDgQW +BBRnJtxhYmeE28Z0t3KMowmzs8ktkzAfBgNVHSMEGDAWgBRnJtxhYmeE28Z0t3KM +owmzs8ktkzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI +ADBFAiEAtsYmah+kECom1sHEUe+eTJmJYjHDVzlxpw30MKEWQFYCIBqGAPxit0db ++E+dYAs0QqyXVog8D6vqWBAn3DJmNkKL +-----END CERTIFICATE----- diff --git a/src/test/resources/gm/gmensdk.crt b/src/test/resources/gm/gmensdk.crt new file mode 100644 index 00000000..5bd84096 --- /dev/null +++ b/src/test/resources/gm/gmensdk.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBgTCCASagAwIBAgIJAMNVhQGVGV3RMAoGCCqBHM9VAYN1MDoxEjAQBgNVBAMM +CWFnZW5jeS1nbTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5 +MCAXDTIyMDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjAzMQwwCgYDVQQDDANz +ZGsxEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWVuc2RrMFkwEwYHKoZI +zj0CAQYIKoEcz1UBgi0DQgAEm/yqjgB6Uj248VaGoKlAFHfMArVmdb6Fi8qJ9Eo5 +xtD+q5p2Olq3T9y334SztTKNtoezyfVYx5kiFXaPXFyjj6MaMBgwCQYDVR0TBAIw +ADALBgNVHQ8EBAMCAzgwCgYIKoEcz1UBg3UDSQAwRgIhAMbxf1yfmW21T1KQC4rs +hw9FNU5qqWeEQDS8EZWr4h3fAiEAgRzV3gVsgxKaIPlgipaQE8mOZKAp4zVuglHT +afeLeI4= +-----END CERTIFICATE----- diff --git a/src/test/resources/gm/gmensdk.key b/src/test/resources/gm/gmensdk.key new file mode 100644 index 00000000..68cc246c --- /dev/null +++ b/src/test/resources/gm/gmensdk.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgwKEROs61A4CO8XUl +bY5XLdNsfBTEpYhenmdkB2aPjkGhRANCAASb/KqOAHpSPbjxVoagqUAUd8wCtWZ1 +voWLyon0SjnG0P6rmnY6WrdP3LffhLO1Mo22h7PJ9VjHmSIVdo9cXKOP +-----END PRIVATE KEY----- diff --git a/src/test/resources/gm/gmsdk.crt b/src/test/resources/gm/gmsdk.crt new file mode 100644 index 00000000..158e75c2 --- /dev/null +++ b/src/test/resources/gm/gmsdk.crt @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIBfzCCASSgAwIBAgIJAMNVhQGVGV3QMAoGCCqBHM9VAYN1MDoxEjAQBgNVBAMM +CWFnZW5jeS1nbTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5 +MCAXDTIyMDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjAxMQwwCgYDVQQDDANz +ZGsxEzARBgNVBAoMCmZpc2NvLWJjb3MxDDAKBgNVBAsMA3NkazBZMBMGByqGSM49 +AgEGCCqBHM9VAYItA0IABJTrIRpey2YTxds+wzs99vygmTCSzfM9zolzhJM2JZ2h +lPJj2EkW7sOi2ipAnl3vqeYMbPSO0FfO62kdSA48ZzSjGjAYMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgbAMAoGCCqBHM9VAYN1A0kAMEYCIQCbDltY/aWbvzQXFDA39io3 +eYJef74SqvBq15SCHTodRQIhALZyL0wOR5b6mF8CpZ1f6PgCfS65MOD+FMu68ROs +iyP9 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBxzCCAW2gAwIBAgIJAPuprJr9njTsMAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM +B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX +DTIyMDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjA6MRIwEAYDVQQDDAlhZ2Vu +Y3ktZ20xEzARBgNVBAoMCmZpc2NvLWJjb3MxDzANBgNVBAsMBmFnZW5jeTBZMBMG +ByqGSM49AgEGCCqBHM9VAYItA0IABJP6Z3Uy/grdbotZz+tG7Oq98qMAymmo9ZH3 +rFLqVirxVld8Ap4UI5VWhxqmlrd+DEV/71CYhF+29tmtwqovaf+jXTBbMB0GA1Ud +DgQWBBTVg/2i5aCyPW5yGkQlrgQoXIWWdTAfBgNVHSMEGDAWgBRnJtxhYmeE28Z0 +t3KMowmzs8ktkzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGD +dQNIADBFAiEAlDh3QzLPvJRxGLWvElV+as4KIJBZkcsxf7qzciogRsoCID6zazCa +wPZ/M/cjX2nVkBZRfOg98swfubSkB4A4RGDs +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBxDCCAWqgAwIBAgIJAIK0FHy8gSBHMAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM +B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX +DTIyMDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjA3MRAwDgYDVQQDDAdnbWNo +YWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjBZMBMGByqG +SM49AgEGCCqBHM9VAYItA0IABPzo9TYTFPRUcy4RealZ80US9iKtPDbMb+cVL0TE +TvVj+Pg6Pr0T2Rstib4jyBYDYnzko8RrPTNy5Fo/XnYbzpmjXTBbMB0GA1UdDgQW +BBRnJtxhYmeE28Z0t3KMowmzs8ktkzAfBgNVHSMEGDAWgBRnJtxhYmeE28Z0t3KM +owmzs8ktkzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI +ADBFAiEAtsYmah+kECom1sHEUe+eTJmJYjHDVzlxpw30MKEWQFYCIBqGAPxit0db ++E+dYAs0QqyXVog8D6vqWBAn3DJmNkKL +-----END CERTIFICATE----- diff --git a/src/test/resources/gm/gmsdk.key b/src/test/resources/gm/gmsdk.key new file mode 100644 index 00000000..c0ba1d3d --- /dev/null +++ b/src/test/resources/gm/gmsdk.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgkum/NmA9fBXWkDie +QK2kgCQUneLu3cfNgFvn2pYCo/ehRANCAASU6yEaXstmE8XbPsM7Pfb8oJkwks3z +Pc6Jc4STNiWdoZTyY9hJFu7DotoqQJ5d76nmDGz0jtBXzutpHUgOPGc0 +-----END PRIVATE KEY----- diff --git a/src/test/resources/gm/gmsdk.publickey b/src/test/resources/gm/gmsdk.publickey new file mode 100644 index 00000000..915cd46b --- /dev/null +++ b/src/test/resources/gm/gmsdk.publickey @@ -0,0 +1 @@ +94eb211a5ecb6613c5db3ec33b3df6fca0993092cdf33dce8973849336259da194f263d84916eec3a2da2a409e5defa9e60c6cf48ed057ceeb691d480e3c6734 diff --git a/src/test/resources/json-schema-cpt.json b/src/test/resources/json-schema-cpt.json new file mode 100644 index 00000000..70e93da0 --- /dev/null +++ b/src/test/resources/json-schema-cpt.json @@ -0,0 +1,24 @@ +{ + "title": "cpt templet", + "description": "five information requirements for users", + "properties" : { + "id": { + "type": "string", + "description": "the weid of certificate owner" + }, + "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"] +} \ No newline at end of file diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml new file mode 100644 index 00000000..db028916 --- /dev/null +++ b/src/test/resources/log4j2.xml @@ -0,0 +1,100 @@ + + + + ./logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org1.txt b/src/test/resources/org1.txt index a18e4ba0..182da3ed 100644 --- a/src/test/resources/org1.txt +++ b/src/test/resources/org1.txt @@ -1,2 +1,2 @@ -publicKey:4152630134607745313775653941373712642376482837388159007706431164834407808290456176569372213582021586381145279900416808342958821437075568109344613716670953 -privateKey:58317564669857453586637110679746575832914889677346283755719850144028639639651 \ No newline at end of file +publicKey:61648715783262993569524833473218300147096886149625191140008176443432637705010301562844338994634470121084706056348088101890813246949904622670239758638712304 +privateKey:95190837481536383166137149464958960030030752301426973662112256567139589090597 \ No newline at end of file diff --git a/src/test/resources/policy.json b/src/test/resources/policy.json new file mode 100644 index 00000000..73b5c66b --- /dev/null +++ b/src/test/resources/policy.json @@ -0,0 +1,20 @@ +{ + "extra": { + "extra1": "", + "extra2": "" + }, + "id": 123456, + "version": 1, + "orgId": "organizationA", + "policyPublisherWeId": "did:weid:0x0231765e19955fc65133ec8591d73e9136306cd0", + "policy": { + "1000": { + "fieldsToBeDisclosed": { + "id": 1, + "name": 1, + "gender": 0, + "age": 1 + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/private_key b/src/test/resources/private_key new file mode 100644 index 00000000..3bceba5a --- /dev/null +++ b/src/test/resources/private_key @@ -0,0 +1 @@ +49191370627614877492996337821917274297863513005433547861103892894089436256261 \ No newline at end of file diff --git a/src/test/resources/public_key b/src/test/resources/public_key new file mode 100644 index 00000000..aec4b2e3 --- /dev/null +++ b/src/test/resources/public_key @@ -0,0 +1 @@ +5686332858406600098574930615286920155179124750677701187633916230205742334882670952535475018419229666394535946783087534972161773024961235927824774898541110 \ No newline at end of file diff --git a/src/test/resources/sdk.crt b/src/test/resources/sdk.crt new file mode 100644 index 00000000..f6142d1c --- /dev/null +++ b/src/test/resources/sdk.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7zCCAdcCCQC5y7aXXQc4qDANBgkqhkiG9w0BAQsFADA2MQ8wDQYDVQQDDAZh +Z2VuY3kxEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAXDTIy +MDcyMDEyMTQ1M1oYDzIxMjIwNjI2MTIxNDUzWjA7MRMwEQYDVQQDDApGSVNDTy1C +Q09TMRMwEQYDVQQKDApmaXNjby1iY29zMQ8wDQYDVQQLDAZhZ2VuY3kwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7P+9jzusAzawLEAwO0uGK7QINVGsn +xSQZwyYi2utupciqNgc28HDdgPIxr6h176K3dU34DUyTKwXqFX3jiXobR0N2L0rQ +61WiwBHoDP3DLFY91csLBX26AKGkHzYzbXAA/J0W3SlsayG8uD1VANIqF2Bz0zS4 +MIxcqQLJfqSjutT2QRUfDC9LpsAhgyB8VAFnzS2/m46wMXPtU+jloiXJyW8DjHIC +eS68bbxDZy/4laFl6W7PwkkX2NwKHFgsKMDHGGt5UYze4Hmy723wT2ZTCOaz15D6 +XpJ7XDzkSuLLZ5J+1ZKuA6XC0coeCnp8jHRL5T+UTmuBPdi8Y/l2mh2fAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAE5SO/ZA7u1W2oTnF+okoI2y//E4CjiLTgf6A+P5 +RyOgMpxPSl/xsZ8uaxa1X2jOFsoSg9JaTyZPUw1cvk66fTc3tjhRlO/KJQNfYvT+ +WHh3zrsB01y49Wjf8ef4Zy2/HdSb8CcuVgmxKwQQMlCGAbNU0pkuhj8C7lFLCqa1 +IcNKdlj8qlMUr0JHAJXEENbGc8mMTr2sJlDj7NcVDIMiEhJLv4APv6Kb4/KWLoH2 +11T/rw0xaFfBqMjpxnzgfL4x2tWMq4DgnHhY5p+lWFcbno/94T8hmmyOKvlmuOr+ +Ye+W2gfu5zlowG4aeYarhAvpp02huOFBjJ5kM12//WF1rK8= +-----END CERTIFICATE----- diff --git a/src/test/resources/sdk.key b/src/test/resources/sdk.key new file mode 100644 index 00000000..9eaed9b9 --- /dev/null +++ b/src/test/resources/sdk.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7P+9jzusAzawL +EAwO0uGK7QINVGsnxSQZwyYi2utupciqNgc28HDdgPIxr6h176K3dU34DUyTKwXq +FX3jiXobR0N2L0rQ61WiwBHoDP3DLFY91csLBX26AKGkHzYzbXAA/J0W3SlsayG8 +uD1VANIqF2Bz0zS4MIxcqQLJfqSjutT2QRUfDC9LpsAhgyB8VAFnzS2/m46wMXPt +U+jloiXJyW8DjHICeS68bbxDZy/4laFl6W7PwkkX2NwKHFgsKMDHGGt5UYze4Hmy +723wT2ZTCOaz15D6XpJ7XDzkSuLLZ5J+1ZKuA6XC0coeCnp8jHRL5T+UTmuBPdi8 +Y/l2mh2fAgMBAAECggEAWI7FVivfQvMCofzF5yDfIIg1Bz7cquN2zmRYHfXxkNQB +UlbZFKekiW3ZnZwZDSX3i9KDvIP1qkiXtHzTnBBB2rLaegOl26bhSmaSUXALeAn5 +A6egLqc7LgPsbqWASdRBO4Y9eTnBxI/qVcnA3/nSa6vApybFcTMsvwoD0m39yZzc +roBhgwZ+W38yJ836Z7xfR8gP9gpE252W81T87wQu9dYnIaNcaIk+SuAMQvZ8x3Rl +VnDZh3a+uxBguDF2yTincaDXJZr/M+bnQf6G4gYgY/2oMnj0jA3twm1Smwrvat2V ++DCnkUP+ZqMwAOmoDm/pxft79vqtwOfhqDVG4iA+GQKBgQDi8qhUFGeZe67APGc4 +8NrwGd5I/SP+o/XwmnDAtC7YLrvmbkOAabCPWW8rSAwXy3Ml059t06XymKonvRFL +r04nOXgHuo05WhkEd8VaaBUq5v/ejRktxJ4Tm0+JL1zzLSvnPza0AhzxNfFJr4M2 +h6+p8NyjrSODmLd0H8X4TBa05QKBgQDTOFL8oThNJXLtU+yZ5o0WltPpin2/9Adb +xSozv36aKW+IEqI8VkHSiUHjNlrS8k9RAPz8N2+IfhVCRneYDKE9tvRGH5Da8uaa +UQ/SGL33UGYhVUra3R/q/vr6H5QcfBrwNUQzPXfqno4zI7WVm62A8E23PvwE/jm1 +R9OoJraEMwKBgC2FEGA064aseSOTufyAytknxx8KryKPDnBg+cadHVw9G3Efoqhq +CoDmJlcfD1Xid8kZhjvIHNvo5RAtav+sPNe/PiUGtPbQ7H2p7Eqy37QIO0APOwKk +EjTKjQxuFI2t/MVYN4epeNakxC3MZ1wToRdL+WVW/+2QPxOqn9GqqU9FAoGBAIwH +czz4xRKgGSkt0lXVewPWynax0dxIM/irJedYtN4PSlmzwMqvhMPHK18u0de3vM2/ +EflD5zVeIUnm3bJ37Q21FQzIMIh3MFpuE0b+EDK9onfGy/F9V4O7tzfLZ63auSE2 +rxgpUC7DHxLYQbIFm2k35s3te7bzs95y1+dKgwXxAoGANfcf3wav+/guwjd5y5Fd +LMMuj3s9SXe3qZhC8YBUCwD1VJ4M5mT/l+DP//+20tk4QeGPycSFZohMnUbbKT+Q +CQmx5NsoJQ8KT5chYJ8P4JKvezdxYP9Vv3gGt4JJHKERgvy057NA6KxbbjL7AnUU +7GbmJqjLpYS+9KZGaLgVnNo= +-----END PRIVATE KEY----- diff --git a/src/test/resources/test-hash-pic.png b/src/test/resources/test-hash-pic.png new file mode 100644 index 00000000..792eab8a Binary files /dev/null and b/src/test/resources/test-hash-pic.png differ diff --git a/src/test/resources/test-multilevel-claim.json b/src/test/resources/test-multilevel-claim.json new file mode 100644 index 00000000..cc8257f2 --- /dev/null +++ b/src/test/resources/test-multilevel-claim.json @@ -0,0 +1,65 @@ +{ + "courses": [ + { + "code": "123456", + "duration": "2019-08-19", + "endDate": "2019-08-19", + "grade": "A", + "language": "中文", + "score": 99, + "startDate": "2019-08-19", + "title": { + "cn": "語文", + "en": 0 + } + }, + { + "code": 321654, + "duration": "2019-08-19", + "endDate": "2019-08-19", + "grade": "A", + "language": "英文", + "score": 99, + "startDate": "2019-08-19", + "title": { + "cn": "數學", + "en": 0 + } + } + ], + "cert": { + "category": { + "cn": "證書", + "en": 0 + }, + "code": "123456", + "issueDate": "2019-08-19", + "permanent": "shenzhen", + "title": { + "cn": "學生證書", + "en": 0 + }, + "totalDuration": "10年", + "validBefore": "2029-08-19" + }, + "fullname": { + "cn": 0, + "en": "shenzhen studentcert" + }, + "issuers": [ + { + "name": { + "cn": "深圳市教育局", + "en": 0 + } + }, + { + "name": { + "cn": "教育部", + "en": 0 + } + } + ], + "did": "123456789", + "weid": "did:weid:101:0xa2c6ef0ea932fd3332da818a2608cb7665e55895" +} \ No newline at end of file diff --git a/src/test/resources/test-multilevel-cpt.json b/src/test/resources/test-multilevel-cpt.json new file mode 100644 index 00000000..fd4df673 --- /dev/null +++ b/src/test/resources/test-multilevel-cpt.json @@ -0,0 +1,171 @@ +{ + "$id": "certs/v1.0", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "StudentCert", + "type": "object", + "required": [ "did", "fullname", "cert", "issuers"], + "properties": { + "did": + {"type": "string", + "name": "DID" + }, + "weid": + {"type": "string", + "name": "WEID" + }, + "fullname": { + "type": "object", + "properties": { + "cn": { + "type": "string", + "name": "中文全名" + }, + "en": { + "type": "string", + "name": "英文全名" + } + } + }, + + "cert":{ + "type": "object", + "name": "证书", + "required": ["code", "title", "category", "issueDate"], + "properties": { + "code": + {"type": "string", + "name": "证书代码" + }, + "title": { + "type": "object", + "name": "题目", + "properties": { + "cn": + {"type": "string", + "name": "中文名称" + }, + "en": + {"type": "string", + "name": "英文名称:" + } + } + }, + "category": { + "type": "object", + "name": "种类", + "properties": { + "cn": + {"type": "string", + "name": "中文名称" + }, + "en": + {"type": "string", + "name": "英文名称" + } + } + }, + "totalDuration": { + "type": "number", + "name": "有效时长" + }, + "issueDate": { + "type": "string", + "name": "签发时间", + "format": "date-time" + }, + "validBefore": { + "type": "string", + "name": "验证有效期", + "format": "date-time" + }, + "permanent": + {"type": "boolean", + "name": "是否永久有效" + } + } + }, + + "issuers": { + "type": "array", + "name": "发布机构", + "minItems": 1, + "items": { + "type": "object", + "name": "机构名称", + "properties": { + "name": { + "type": "object", + "name": "发布机构名称", + "properties": { + "cn": + {"type": "string", + "name": "机构中文名" + }, + "en": + {"type": "string", + "name": "机构英文名" + } + } + } + } + } + }, + + "courses": { + "type": "array", + "name": "课程", + "items": { + "type": "object", + "name": "课程名称", + "properties": { + "code": + {"type": "string", + "name": "课程代码" + + }, + "title": { + "type": "object", + "name": "课程名称", + "properties": { + "cn": + {"type": "string", + "name": "课程中文名" + }, + "en": + {"type": "string", + "name": "课程英文名" + } + } + }, + "startDate": { + "type": "string", + "name": "开始时间", + "format": "date" + }, + "endDate": { + "type": "string", + "name": "终止时间", + "format": "date" + }, + "duration": { + "type": "number" + }, + "grade": + {"type": "string", + "name": "等级" + }, + "score": + { + "type": "string", + "name": "分数" + }, + "language": + { + "type": "string", + "name": "语言" + } + } + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/test-policy.json b/src/test/resources/test-policy.json new file mode 100644 index 00000000..1e393347 --- /dev/null +++ b/src/test/resources/test-policy.json @@ -0,0 +1,80 @@ +{ + "id" : 123456, + "version" : 1, + "orgId" : "organizationA", + "policyPublisherWeId" : "did:weid:0x0231765e19955fc65133ec8591d73e9136306cd0", + "policy" : { + "1000" : { + "fieldsToBeDisclosed" : { + "weid" : 1, + "gender" : 1, + "name" : 1, + "age" : 1 + } + }, + "1002" : { + "fieldsToBeDisclosed" : { + "weid" : 1, + "data" : { + "id" : 0, + "sipTellAddress" : 1, + "userlevel" : 0 + }, + "meta" : { + "code" : 1, + "error" : 0, + "info" : 1 + }, + "name" : 0 + } + }, + "1001" : { + "fieldsToBeDisclosed" : { + "weid" : 1, + "courses" : [ { + "code" : 1, + "duration" : 1, + "endDate" : 1, + "grade" : 1, + "language" : 1, + "score" : 1, + "startDate" : 1, + "title" : { + "cn" : 1, + "en" : 0 + } + } ], + "cert" : { + "category" : { + "cn" : 1, + "en" : 0 + }, + "code" : 1, + "issueDate" : 1, + "permanent" : 1, + "title" : { + "cn" : 1, + "en" : 0 + }, + "totalDuration" : 1, + "validBefore" : 1 + }, + "fullname" : { + "cn" : 0, + "en" : 1 + }, + "issuers" : [ { + "name" : { + "cn" : 1, + "en" : 0 + } + } ], + "did" : 1 + } + } + }, + "extra" : { + "extra1" : "", + "extra2" : "" + } +} \ No newline at end of file diff --git a/src/test/resources/test-singlelevel-claim.json b/src/test/resources/test-singlelevel-claim.json new file mode 100644 index 00000000..099994da --- /dev/null +++ b/src/test/resources/test-singlelevel-claim.json @@ -0,0 +1,6 @@ +{ + "weid": "did:weid:101:0xce618fb7fbacaf6398a0b4b78bf2dd942c8c49c7", + "name": "張三", + "gender": "男", + "age":26 +} \ No newline at end of file diff --git a/src/test/resources/test-singlelevel-cpt.json b/src/test/resources/test-singlelevel-cpt.json new file mode 100644 index 00000000..f0a6ce61 --- /dev/null +++ b/src/test/resources/test-singlelevel-cpt.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "five information requirements for users", + "title": "身份证", + "type": "object", + "properties": { + "weid": { + "type": "string", + "name": "微ID", + "description": "user weId" + }, + "age": { + "description": "the age of certificate owner", + "type": "integer", + "name": "年龄" + }, + "gender": { + "description": "the gender of certificate owner", + "enum": [ + "F", + "M" + ], + "type": "string", + "name": "性别" + }, + "name": { + "description": "the name of certificate owner", + "type": "string", + "name": "名字" + } + }, + "required": [ + "name", + "age" + ] +} \ No newline at end of file diff --git a/src/test/resources/test-spectpl-claim.json b/src/test/resources/test-spectpl-claim.json new file mode 100644 index 00000000..beb8e7ea --- /dev/null +++ b/src/test/resources/test-spectpl-claim.json @@ -0,0 +1,5 @@ +{ + "name": "張三", + "date":"2019-09-03", + "issuer": "This is an institution name." +} \ No newline at end of file diff --git a/src/test/resources/test-spectpl-cpt.json b/src/test/resources/test-spectpl-cpt.json new file mode 100644 index 00000000..d8c06043 --- /dev/null +++ b/src/test/resources/test-spectpl-cpt.json @@ -0,0 +1,19 @@ +{ + "title": "cpt templet for specify pdf template", + "description": "three information requirements for users", + "properties" : { + "name": { + "type": "string", + "description": "the name of certificate owner" + }, + "date": { + "type": "string", + "description": "the date of issue" + }, + "issuer": { + "type": "string", + "description": "the issuer" + } + }, + "required": ["name", "date", "issuer"] +} \ No newline at end of file diff --git a/src/test/resources/test-spectpl-policy.json b/src/test/resources/test-spectpl-policy.json new file mode 100644 index 00000000..926bc5c4 --- /dev/null +++ b/src/test/resources/test-spectpl-policy.json @@ -0,0 +1,15 @@ +{ + "id": 123456, + "version": 1, + "orgId": "organizationA", + "policyPublisherWeId": "did:weid:0x0231765e19955fc65133ec8591d73e9136306cd0", + "policy": { + "1005": { + "fieldsToBeDisclosed": { + "name" : 1, + "date" : 1, + "issuer" : 1 + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/test-template-complex.pdf b/src/test/resources/test-template-complex.pdf new file mode 100644 index 00000000..844b162b Binary files /dev/null and b/src/test/resources/test-template-complex.pdf differ diff --git a/src/test/resources/test-template.pdf b/src/test/resources/test-template.pdf new file mode 100644 index 00000000..fcf66ef2 Binary files /dev/null and b/src/test/resources/test-template.pdf differ diff --git a/src/test/resources/weidentity.properties.tpl b/src/test/resources/weidentity.properties.tpl new file mode 100644 index 00000000..70340ef7 --- /dev/null +++ b/src/test/resources/weidentity.properties.tpl @@ -0,0 +1,156 @@ +####################################################################################################### +# # +# application config # +# # +####################################################################################################### +# Deploy WeIdentity with blockchain or only database +deploy.style=${DEPLOY_STYLE} +# Crypto type, only use for deploy with database, 0 for ECDSA, 1 for SM +crypto.type=${CRYPTO_TYPE} + +# The organization ID for AMOP communication. +blockchain.orgid=${ORG_ID} + +# The Blockchain Type +blockchain.type=${CHAIN_TYPE} + +# The Chain Id +chain.id=${CHAIN_ID} + +# AMOP Config +# Timeout for amop request, default: 5000ms +amop.request.timeout=5000 + +amop.id=${AMOP_ID} + +# Blockchain node info. +nodes=${BLOCKCHIAN_NODE_INFO} + + +####################################################################################################### +# # +# persistence config # +# # +####################################################################################################### +# Persistence Layer configurations. Do NOT change this if you are not using Persistence Layer features! +#Support the persistence of mysql and redis. You can choose the type of persistence. +persistence_type=${PERSISTENCE_TYPE} + +# MySQL connection config +# Support multiple data source configurations with comma-separated multiple data sources. +datasource.name=datasource1 + +# The configuration of each data source is prefixed by the name of the data source. +datasource1.jdbc.url=jdbc:mysql://${MYSQL_ADDRESS}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai +datasource1.jdbc.driver=com.mysql.cj.jdbc.Driver +datasource1.jdbc.username=${MYSQL_USERNAME} +datasource1.jdbc.password=${MYSQL_PASSWORD} +datasource1.jdbc.maxActive=50 +datasource1.jdbc.initialSize=5 +datasource1.jdbc.minIdle=5 +datasource1.jdbc.maxIdle=5 +datasource1.jdbc.maxWait=10000 +datasource1.jdbc.timeBetweenEvictionRunsMillis=600000 +datasource1.jdbc.numTestsPerEvictionRun=5 +datasource1.jdbc.minEvictableIdleTimeMillis=1800000 + +# Redis config +# If you want to configure redis in cluster mode, enter multiple node addresses separated by commas. +redis.url=${REDIS_ADDRESS} +redis.password=${REDIS_PASSWORD} +redis_single.database=0 +redis_cluster.idle_connection_timeout=10000 +redis_cluster.connect_timeout=10000 +redis_cluster.timeout=3000 +redis_cluster.slave_connection_minimum_idle_size=10 +redis_cluster.slave_connection_pool_size=64 +redis_cluster.master_connection_minimum_idle_size=10 +redis_cluster.master_connection_pool_size=64 + + +####################################################################################################### +# # +# persistence domain config # +# # +####################################################################################################### +# Domain configuration, which divides colons into two segments, the first segment is the name of the data source, +# the second segment is the name of the table, and if not, the default is the first data source and the default table `sdk_all_data`, +# Multiple domains can be configured at the same time. +# example: +# domain.credential=datasource1:credential_info +# domain.credential.timeout=86400000 +# domain.weIdDocument=datasource1:weid_document_info +# domain.credential.timeout=86400000 + +# the default domain +domain.defaultInfo=datasource1:default_info +domain.defaultInfo.timeout=31556908799941 + +# the domain for save encrypt Key +domain.encryptKey=datasource1:encrypt_key_info +domain.encryptKey.timeout=31556908799941 + +# zkp credential template secret +domain.templateSecret=***REMOVED*** +domain.templateSecret.timeout=31556908799941 + +# zkp credential master secret +domain.masterKey=***REMOVED*** + +# zkp credential signature +domain.credentialSignature=datasource1:credential_signature + +# weid auth info +domain.weIdAuth=datasource1:weid_auth + +# the domain for save resource +domain.resourceInfo=datasource1:resource_info +domain.resourceInfo.timeout=31556908799941 + +# tables for running locally +local.weIdDocument=datasource1:table_weid_document +local.cpt=datasource1:table_cpt +local.policy=datasource1:table_policy +local.presentation=datasource1:table_presentation +local.role=datasource1:table_role +local.authorityIssuer=datasource1:table_authority_issuer +local.specificIssuer=datasource1:table_specific_issuer +local.evidence=datasource1:table_evidence + + +####################################################################################################### +# # +# credential related config # +# # +####################################################################################################### +# You can configure the maximumSize of the default cache module through caffeineCache.maximumSize.xxx. +caffeineCache.maximumSize.SYS_CPT=100 + +# Salt length for Proof creation. +salt.length=5 + +# Default length of array value in CPT when creating credential based on ZKP. +zkp.cpt.array.length=5 + + +####################################################################################################### +# # +# endpoint Service config # +# # +####################################################################################################### +# Endpoint Service Integration-side parameters +# Listener port required to be opened for RPC Server, default: 6010 +endpoint.listener.port=6010 + + +####################################################################################################### +# # +# timestamp Service config # +# # +####################################################################################################### +# Timestamp Service Parameters +wesign.accessTokenUrl= +wesign.signTicketUrl= +wesign.timestampUrl= +wesign.appId= +wesign.secret= \ No newline at end of file diff --git "a/task-38 Weldentity\345\234\272\345\275\225\346\241\210\344\276\213\345\242\236\345\212\240\344\270\215\345\220\214\347\232\204\345\272\224\347\224\250\345\234\272\346\231\257/task38.md" "b/task-38 Weldentity\345\234\272\345\275\225\346\241\210\344\276\213\345\242\236\345\212\240\344\270\215\345\220\214\347\232\204\345\272\224\347\224\250\345\234\272\346\231\257/task38.md" new file mode 100644 index 00000000..e8194792 --- /dev/null +++ "b/task-38 Weldentity\345\234\272\345\275\225\346\241\210\344\276\213\345\242\236\345\212\240\344\270\215\345\220\214\347\232\204\345\272\224\347\224\250\345\234\272\346\231\257/task38.md" @@ -0,0 +1,37 @@ +# 案例:个人收入场景证明 + +- 背景 + +合作方是一家中小企业,在招聘员工时需要对员工的个人收入进行真实性验证,用于确定新员工的薪水。存在的问题是:对员工而言,需要去每个机构花费大量时间精力获取最新版的材料,然后才能开具个人收入证明文件。对企业而言,材料的获取和流转的过程中可能遭到篡改,而且缺乏验证材料真实性的手段。 + +- 参与方 + + - 员工 + - 前雇主单位 + - 现雇主单位 + - 银行 + - 社保局 +- WeIdentity解决方案及基本流程 + + 1. 员工、银行、公司分别进行WeIdentity DID注册及KYC认证; + 2. 员工向前雇主公司申请工作证明凭证(Credential)、离职证明凭证(Credential); + 3. 员工向银行申请个人收入凭证(Crdential),向社保局申请社保缴纳凭证(Crdential); + 4. 员工将这些凭证(Credential)挂到自己的个人主页上,或者直接提交给现雇主公司; + 5. 现雇主公司通过凭证验证(Verify)接口对上述凭证(Credential)进行验证; + 6. 验证通过,现雇主公司发放入职offer,并根据个人收入凭证(Crdential)进行定薪。 + +# 案例:结合IOT实体场景 + +- 背景 + +智能制造是指不断引入各种先进技术,包括物联网、大数据、人工智能等,实现制造过程的智能化和数字化,提高生产效率、降低成本、提升产品质量。然而,随着设备数量的增加和数据量的增大,智能制造面临着设备身份管理、数据安全和可追溯性问题,并且每个设备的相关信息(例如生产日期、运行时间、质量检测报告等)也可能存在被伪造和篡改的风险。 + +- 参与方: + - 设备制造商 + - 物联网设备 + - 运营商 +- WeIdentity解决方案及基本流程 + 1. 每个制造机器都可以被分配一个独一无的DID和DID Doc内容,这个DID由设备的制造商生成并赋予每台机器; + 2. 运营商在接收到设备后,可以根据每台设备中的可验证凭证(Credential)信息,去校验该设备运行时间、质量报告等是否满足需求标准; + 3. 设备运行时,与其他设备或服务器进行通信,它会使用这个私钥对通信内容进行签名,只有在对应的公钥才能解读这个签名,以证明设备身份的合法性; + 4. 在某些场景下,不同物联网设备之间通信也需要某些权限的校验,可以通过给设备颁发不同的可验证凭证(Credential),如果凭证(Credential)满足条件,则进行通信或数据共享。 diff --git a/weidentity-task1/README.md b/weidentity-task1/README.md new file mode 100644 index 00000000..35fb9498 --- /dev/null +++ b/weidentity-task1/README.md @@ -0,0 +1,255 @@ +# 基于did的单点登录 + +## 1.赛题描述 + +参考[login.xyz](https://docs.login.xyz/) 实现基于Weldentity或者FISCO BCOS地址的单点登录Demo + +(实现提供简单的网站登录页面,输入Weld和签名即可登录,签名可以通过任意方式得到,但是签名的内容由demo的服务器在登录的时候提供,鉴权过程可以使用任意协议比如OAuth2.0,具体的鉴权方式则是调用Weldentity的接口验证前端提供的Weldentity),Sign-In with Weldentity or FISCO BCOS + +## 2.题目分析 + +### 2.1 概要 + +- login.xyz 概念和实现原理; +- OAuth 2.0鉴权协议; +- Weldentity 相关接口; + +### 2.2 login.xyz + +sign-in with Ethereum是一种使用以太坊区块链技术进行身份验证的方式。它的技术原理如下: + +- 用户使用以太坊钱包(如 MetaMask)创建自己的数字身份,并生成一个公钥和私钥对; +- 用户在登录页面上选择 "sign-in with Ethereum" 选项,并使用以太坊钱包进行身份验证; +- 登录页面向用户的钱包发送一个随机字符串,要求用户用私钥对该字符串进行签名; +- 用户使用钱包中的私钥对随机字符串进行签名,并将签名结果发送回登录页面; +- 登录页面使用公钥验证签名结果的有效性,如果验证通过,则认为用户已经通过身份验证,可以登录系统; + +上述实现的核心逻辑就是:私钥签名 -> 公钥解密 -> 对比内容通过则证明用户持有公钥对应的私钥 -> 证明用户身份合法性 + +### 2.3 OAuth 2.0鉴权协议 + +详细的oatuh2.0协议相关理论知识可以参考[oatuh2.0](https://oauth.net/2/),这里我们介绍下当前项目下,每个模块分别在对应协议中角色。在oauth2.0中,包括如下角色: + +- 资源所有者:拥有受保护的资源(如用户); +- 客户端:代表资源所有者访问受保护的资源; +- 授权服务器:颁发访问令牌(access token)给客户端,以便客户端能够访问受保护的资源; +- 资源服务器:存储受保护的资源,并对客户端发出的访问令牌进行验证。 + +在该项目中,资源所有者即拥有did的用户,客户端则是指不同的业务系统,授权服务器则是指did认证服务系统,为了尽量引入少的系统,我们授权服务器和资源服务器使用同一系统实现,都在did认证服务系统中实现。 + +### 2.4 WeIdentity-Rest-Service + +我们通过搭建并调用`WeIdentity-Rest-Service`([code github地址](https://github.com/WeBankBlockchain/WeIdentity-Rest-Service/tree/develop))服务完成did相关的功能。主要接口如下: + +- encode: + - 请求地址:http://{{host}}:{{httpport}}/weid/api/encode + - 入参: + ```json + { + "functionArg": { + "publicKey": "712679236821355231513532168231727831978932132185632517152735621683128" + }, + "transactionArg": { + "nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039" + }, + "functionName": "createWeId", + "v": "1.0.0" + } + ``` + - 返回值: + ```json + { + "respBody": { + "blockLimit": "570", + "data": "0x635ef5a5000000000000000000000000133419735082a1207bf4fb1f067da39e71865fe1000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000d31363937303932333532303738000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001046469643a776569643a313a307831333334313937333530383261313230376266346662316630363764613339653731383635666531236b6579732d39393230653732642c45643235353139566572696669636174696f6e4b6579323032302c6469643a776569643a313a3078313333343139373335303832613132303762663466623166303637646133396537313836356665312c7a33616e784a536b43716f55427a695a7a326e66385238393442386d47676e67384255767335724a744e424a6535666b364b364c52706154524d3365586b43436a6b4c39647a617533666144794141715a504e61507166646d34727168664e4a357239376745664774533648614e56000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000786469643a776569643a313a3078313333343139373335303832613132303762663466623166303637646133396537313836356665312330346238643861652c57654964656e746974792c68747470733a2f2f6769746875622e636f6d2f576542616e6b426c6f636b636861696e2f57654964656e746974790000000000000000", + "encodedTransaction": "+QNYiGnvXSDiaQnqhRdIduf/hRdIduf/ggI6lLO71DAWvDlB6wv6ikw01dv+NLA1gLkDJGNe9aUAAAAAAAAAAAAAAAATNBlzUIKhIHv0+x8GfaOecYZf4QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANMTY5NzA5MjM1MjA3OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQRkaWQ6d2VpZDoxOjB4MTMzNDE5NzM1MDgyYTEyMDdiZjRmYjFmMDY3ZGEzOWU3MTg2NWZlMSNrZXlzLTk5MjBlNzJkLEVkMjU1MTlWZXJpZmljYXRpb25LZXkyMDIwLGRpZDp3ZWlkOjE6MHgxMzM0MTk3MzUwODJhMTIwN2JmNGZiMWYwNjdkYTM5ZTcxODY1ZmUxLHozYW54SlNrQ3FvVUJ6aVp6Mm5mOFI4OTRCOG1HZ25nOEJVdnM1ckp0TkJKZTVmazZLNkxScGFUUk0zZVhrQ0Nqa0w5ZHphdTNmYUR5QUFxWlBOYVBxZmRtNHJxaGZOSjVyOTdnRWZHdFM2SGFOVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHhkaWQ6d2VpZDoxOjB4MTMzNDE5NzM1MDgyYTEyMDdiZjRmYjFmMDY3ZGEzOWU3MTg2NWZlMSMwNGI4ZDhhZSxXZUlkZW50aXR5LGh0dHBzOi8vZ2l0aHViLmNvbS9XZUJhbmtCbG9ja2NoYWluL1dlSWRlbnRpdHkAAAAAAAAAAAEBgA==" + }, + "loopback": null, + "errorCode": 0, + "errorMessage": "success" + } + ``` +- transcat + - 请求地址:http://{{host}}:{{httpport}}/weid/api/tanscat + - 入参: + ```json + { + "functionArg": {}, + "transactionArg": { + "nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039", + "blockLimit": "570", + "signType": "2", + "data": "0x635ef5a5000000000000000000000000133419735082a1207bf4fb1f067da39e71865fe1000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000d31363937303932333532303738000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001046469643a776569643a313a307831333334313937333530383261313230376266346662316630363764613339653731383635666531236b6579732d39393230653732642c45643235353139566572696669636174696f6e4b6579323032302c6469643a776569643a313a3078313333343139373335303832613132303762663466623166303637646133396537313836356665312c7a33616e784a536b43716f55427a695a7a326e66385238393442386d47676e67384255767335724a744e424a6535666b364b364c52706154524d3365586b43436a6b4c39647a617533666144794141715a504e61507166646d34727168664e4a357239376745664774533648614e56000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000786469643a776569643a313a3078313333343139373335303832613132303762663466623166303637646133396537313836356665312330346238643861652c57654964656e746974792c68747470733a2f2f6769746875622e636f6d2f576542616e6b426c6f636b636861696e2f57654964656e746974790000000000000000", + "signedMessage": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=" + }, + "functionName": "createWeId", + "v": "1.0.0" + } + ``` + - 返回值: + ```json + { + "respBody":"did:weid:1:0x133419735082a1207bf4fb1f067da39e71865fe1", + "loopback":null, + "errorCode":0, + "errorMessage":"success" + } + ``` +- invoke + - 请求地址:http://{{host}}:{{httpport}}/weid/api/invoke + - 入参: + ```json + { + "functionArg": { + "weId":"did:weid:1:0x133419735082a1207bf4fb1f067da39e71865fe1" + }, + "transactionArg": {}, + "v": "1.0.0", + "functionName": "getWeIdDocument" + } + ``` + - 返回值: + ```json + { + "respBody": { + "resolutionMetadata": { + "contentType": "JSON-LD", + "error": null + }, + "weIdDocumentJson": "{\"@context\" : \"https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1\",\n \"id\" : \"did:weid:1:0x3e597137b2dd9009b35f59d2256e671b9145ad51\",\n \"authentication\" : [ {\n \"id\" : \"did:weid:1:0x3e597137b2dd9009b35f59d2256e671b9145ad51#keys-fdf8e284\",\n \"type\" : \"Ed25519VerificationKey2020\",\n \"controller\" : \"did:weid:1:0x3e597137b2dd9009b35f59d2256e671b9145ad51\",\n \"publicKeyMultibase\" : \"z3anxJUsFwuR5AvKRqaTCLJ8fTmQcBZNLNLpyq2dECuvbSC1so8dC3Fvz343q3m7py3uwxXLUbB5dgfH2CX36AMpuoAqPe1nwjaWKrto76tf59R\",\n \"publicKey\" : \"72907716505989393088186550107679567364185218721963761981761904328221802680748\"\n } ],\n \"service\" : [ {\n \"id\" : \"did:weid:1:0x3e597137b2dd9009b35f59d2256e671b9145ad51#04b8d8ae\",\n \"type\" : \"WeIdentity\",\n \"serviceEndpoint\" : \"https://github.com/WeBankBlockchain/WeIdentity\"\n } ]\n}", + "weIdDocumentMetadata": { + "created": null, + "updated": null, + "deactivated": false, + "versionId": 1 + } + }, + "loopback": null, + "errorCode": 0, + "errorMessage": "success" + } + ``` + +上述接口中,encode和transcat主要是为了通过用户的公钥和私钥创建did,供`did-wallet`工具调用,invoke接口则是为了通过did获取公钥信息使用,供did认证系统使用。 + +## 3.系统设计 + +### 3.1 总体设计 + +通过分析题目要求和涉及的技术,系统架构设计如下: + +![image.png](./assets/system_structure.png) + +结合上述的系统架构,主要功能模块包括did钱包、业务系统以及did认证系统这三个模块。 + +### 3.2 did钱包 + +did钱包,用于管理私钥和did信息的客户端,功能类似于MetaMask,其与业务系完全独立,主要功能如下: + +1. 公私钥生成和存储功能; +2. 生成did功能; +3. 使用私钥进行签名功能。 + +#### 时序图 + +```mermaid +sequenceDiagram +did钱包 ->> did钱包 : 生成公私钥 +did钱包 ->> weidentity-rest-service : create did +weidentity-rest-service -->> did钱包 : return did info +``` + +### 3.2 业务系统 + +为了体现sso单点登录的效果,这里我们分别实现两个业务系统,当通过一个业务系统登录成功后,同一did用户在登录另外一个业务系统时,可以根据token信息直接实现登录。 + +根据login.xyz和oauth2.0协议,系统主要实现流程设计如下: + +1. 用户通过did钱包生成公私钥和did信息,此时用户did和对应的did doc已经成功上链; +2. 通过业务系统点击did跳转登录,即Sign-In With WeIdentity,这里会将页面跳转到did认证系统的界面上,认证系统通过用户输入的did和签名信息; +3. 认证系统验证成功后,返回code给业务系统; +4. 业务系统通过code获取access_token,当用户在上述step1中登录成功后,did认证系统会返回一个code,业务系统通过在did认证系统clientId、secret以及code一同提交至did认证系统; +5. 认证成功后,did认证系统会将access_token返回给业务系统,业务系统可以基于该access_token对资源服务器进行访问。 + +#### 时序图 + +```mermaid +sequenceDiagram +业务系统 ->> did认证系统 : loginWithDid +did认证系统 ->> weidentity-rest-service : 根据did获取did doc信息 +weidentity-rest-service -->> did认证系统 : did doc信息 +did认证系统 ->> did认证系统 : 校验did及签名信息 +did认证系统 -->> 业务系统 : 校验成功,返回code授权码 +业务系统 ->> did认证系统 : clientId+secret+code +did认证系统 ->> did认证系统 : 校验信息 +did认证系统 -->> 业务系统 : 校验成功,返回access_token +``` + +### 3.3 认证系统 + +did认证系统是整个项目的核心,其需要实现基于oauth2.0协议的主要功能,能够对访问资源服务器进行认证、授权以及三方客户端的管理等功能。这里我们基于oatuh2.0中`authorization_code`授权模式实现了认证通过http协议对外提供的功能如下: + +1. authorize: 获取授权code,根据客户端注册在认证系统的clientId为客户端生成code码; +2. token:通过code获取token,客户端通过clientId+secret的认证方式,并将code码传送过来,生成token后,返回给客户端; +3. login:该功能是通过did+signature验证用户的身份信息,验证通过则代表用户登录成功; +4. verify:校验第三方客户端即(章节3.2 业务系统)access_token是否合法。 + +## 4.系统实现 + +> 这部分完成主要功能模块的开发工作,介绍该系统主要使用的技术和部分代码实现,所有的核心代码都是通过go语言实现。 + +系统开发的详细实现和介绍在各个代码仓库下的`README.md`中进行讲解,功能模块和代码对应关系如下: + +- did钱包 --> did-wallet +- 业务系统 --> did-client1、did-client2,两个业务系统代码一致 +- 认证系统 --> did-server +- 前端 --> web1、web2,对应两个业务系统的前端 + +项目的目录结构如下图所示。 + +```shell +src +├── did-client +├── did-client2 +├── did-server +├── did-wallet +├── web1 +└── web2 +``` + + +**注意**: + 1. 该系统运行前提条件是,你已经通过官方文档将 `WeIdentity-Rest-Service`和 `fisco-bcos链` 部署并运行,项目运行依赖于did接口,并且会将did上到链上; + 2. 安装go环境,version >= 1.20.x; + +## 5.web前端服务启动 + +### 5.1 前端启动 + +1. 安装node v14.18.x +2. 修改 /web1/vue.config.js文件中的ip和port信息,修改为你需要运行的地址; + +![web conf](assets/config.jpg) + +3. 运行服务 +```shell +# 进入web1目录 +cd web1 +# 首次运行需要先安装依赖 +npm install +npm start +``` + +## 6.主要参考 + +1. [WeIdentity-Rest-Service Doc](https://weidentity.readthedocs.io/zh_CN/latest/docs/weidentity-rest.html) +2. [oauth 2.0协议](https://oauth.net/2/) +3. [oauth 2.0协议使用](https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html) +4. [oauth 2.0 golang](https://github.com/golang/oauth2) + + +## 7.不足和改进 + +本系统目前只实现了赛题要求的最基本功能,包括对于用户的管理、登录状态等都没有实现,其中did认证系统也没有对client进行进一步的管理,只实现了简单的授权和认证功能。 + +为了保证系统简单和便于理解,除了使用 `fisco-bcos`链存储did必要信息外,没有引入其他存储中间件。另外,本系统没有经过专业测试进行详细的测试,只对必要功能进行了单元测试,运行过程中如果存在任何问题或者有不理解的地方,欢迎联系我:liwh1227@foxmail.com。 \ No newline at end of file diff --git a/weidentity-task1/assets/loginin-with-weid-demo.mp4 b/weidentity-task1/assets/loginin-with-weid-demo.mp4 new file mode 100644 index 00000000..028faa9f Binary files /dev/null and b/weidentity-task1/assets/loginin-with-weid-demo.mp4 differ diff --git a/weidentity-task1/assets/system_structure.png b/weidentity-task1/assets/system_structure.png new file mode 100644 index 00000000..c317098a Binary files /dev/null and b/weidentity-task1/assets/system_structure.png differ diff --git a/weidentity-task1/src/did-client/README.md b/weidentity-task1/src/did-client/README.md new file mode 100644 index 00000000..033320e4 --- /dev/null +++ b/weidentity-task1/src/did-client/README.md @@ -0,0 +1,53 @@ +# did client + +did-client的代码实现了整个项目架构中的业务系统,基于go语言(go 1.20)实现,通过`gin`框架实现http服务。 + +## 项目结构 + +代码目录结构如下: + +```shell +├── README.md +├── config +│   └── config.go +├── config.yaml +├── go.mod +├── go.sum +├── httpx +│   ├── handler.go +│   └── router.go +└── main.go +``` +- httpx: 对外提供http服务,供前端调用,router是具体的路由方法,handler是对应的实现; +- config:配置管理功能,读取`config.yaml`文件,该文件中有各配置项的说明; +- main.go: 方法入口。 + +## api接口 + +该客户端提供的主要接口。 + +1. loginWithDid did登录接口 + + 该接口调用后跳转到did登录的认证服务,登录成功后,did认证服务会返回code码。 + +2. callback 回调接口 + + 该接口将`loginWithDid`中获取到的code拼接到url上,并重定向至前端地址,该步骤是为了把code传给前端页面。 + +3. loginWithCode 根据code调用中心系统接口获取token + + 该接口通过调用完成code换取token的步骤。 + +## 使用方式 + +简单介绍系统如何编译和运行。 + +### 启动服务 + +```shell +# 确保系统已经安装go环境 +export GOPROXY="https://goproxy.cn" +export GO111MODULE="on" +export CONF_PATH=./conf_file +go run main.go +``` diff --git a/weidentity-task1/src/did-client/conf_file/config.yaml b/weidentity-task1/src/did-client/conf_file/config.yaml new file mode 100644 index 00000000..6284937d --- /dev/null +++ b/weidentity-task1/src/did-client/conf_file/config.yaml @@ -0,0 +1,17 @@ +# http服务端口 +httpPort: 20000 +# 认证系统信息 +didServerInfo: + ip: "127.0.0.1" + port: 10003 +# did client信息,即在认证系统注册的client信息 +didClientInfo: + ip: "127.0.0.1" + port: 20000 + # did client id和secret,这里要和在did认证系统注册的信息一致 + clientId: "did_client_1" + secret: "***REMOVED***" +# 后端获取code成功后,跳转的前端页面地址 +redirectFront: + ip: "127.0.0.1" + port: 10000 \ No newline at end of file diff --git a/weidentity-task1/src/did-client/config/config.go b/weidentity-task1/src/did-client/config/config.go new file mode 100644 index 00000000..8f6228e9 --- /dev/null +++ b/weidentity-task1/src/did-client/config/config.go @@ -0,0 +1,71 @@ +package config + +import ( + "os" + "sync" + + "github.com/spf13/viper" +) + +var ( + once sync.Once + conf *Config +) + +type Config struct { + path string + HttpPort int + DidServerInfo DidServerInfo `yaml:"didServerInfo"` + DidClientInfo DidClientInfo `yaml:"didClientInfo"` + RedirectFront RedirectFront `yaml:"redirectFront"` +} + +type DidServerInfo struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` +} + +type RedirectFront struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` +} + +type DidClientInfo struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` + ClientId string `yaml:"clientId"` + Secret string `yaml:"secret"` +} + +func ConfigIns() *Config { + return conf +} + +func init() { + once.Do(func() { + conf = new(Config) + }) + + var err error + + conf.path = os.Getenv("CONF_PATH") + if len(conf.path) == 0 { + conf.path, err = os.Getwd() + if err != nil { + panic(err) + } + } + + viper.AddConfigPath(conf.path) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + err = viper.ReadInConfig() + if err != nil { + panic(err) + } + + err = viper.Unmarshal(conf) + if err != nil { + panic(err) + } +} diff --git a/weidentity-task1/src/did-client/go.mod b/weidentity-task1/src/did-client/go.mod new file mode 100644 index 00000000..cf0c60b9 --- /dev/null +++ b/weidentity-task1/src/did-client/go.mod @@ -0,0 +1,45 @@ +module did-client + +go 1.20 + +require ( + github.com/gin-gonic/gin v1.9.1 + github.com/spf13/viper v1.16.0 +) + +require ( + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/weidentity-task1/src/did-client/go.sum b/weidentity-task1/src/did-client/go.sum new file mode 100644 index 00000000..2f48f3f1 --- /dev/null +++ b/weidentity-task1/src/did-client/go.sum @@ -0,0 +1,550 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-github/v37 v37.0.0 h1:rCspN8/6kB1BAJWZfuafvHhyfIo5fkAulaP/3bOQ/tM= +github.com/google/go-github/v37 v37.0.0/go.mod h1:LM7in3NmXDrX58GbEHy7FtNLbI2JijX93RnMKvWG3m4= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/weidentity-task1/src/did-client/httpx/handler.go b/weidentity-task1/src/did-client/httpx/handler.go new file mode 100644 index 00000000..7243e193 --- /dev/null +++ b/weidentity-task1/src/did-client/httpx/handler.go @@ -0,0 +1,116 @@ +package httpx + +import ( + "did-client/config" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/gin-gonic/gin" +) + +type TokenRequest struct { + GrantType string `json:"grant_type"` + Code string `json:"code"` + RedirectUri string `json:"redirect_uri"` +} + +type ThirdClientResp struct { + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + RefreshToken string `json:"refresh_token"` + Scope string `json:"scope"` + TokenType string `json:"token_type"` +} + +// 通过did的方式进行登录 +func loginWithDid(ctx *gin.Context) { + ctx.Redirect(http.StatusSeeOther, loginRedirectUri()) +} + +func loginRedirectUri() string { + return fmt.Sprintf("http://%s:%d/authorize?client_id=%s&response_type=code&scope=all&state=xyz&redirect_uri=http://%s:%d/v1/callback", + config.ConfigIns().DidServerInfo.Ip, config.ConfigIns().DidServerInfo.Port, + config.ConfigIns().DidClientInfo.ClientId, config.ConfigIns().DidClientInfo.Ip, config.ConfigIns().DidClientInfo.Port) +} + +func callback(ctx *gin.Context) { + code := ctx.Query("code") + + fmt.Println(code) + + ctx.Redirect(http.StatusFound, fmt.Sprintf("http://%s:%d/oauth-result?code=%s", config.ConfigIns().RedirectFront.Ip, config.ConfigIns().RedirectFront.Port, code)) +} + +func loginWithCode(ctx *gin.Context) { + code := ctx.Query("code") + + resp, err := getAccessToken(code) + if err != nil { + ctx.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": err.Error(), + }) + ctx.Abort() + return + } + + ret := new(ThirdClientResp) + + err = json.Unmarshal(resp, ret) + if err != nil { + ctx.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": err.Error(), + }) + ctx.Abort() + return + } + + ctx.JSON(http.StatusOK, gin.H{ + "code": 0, + "msg": "success", + "data": ret, + }) +} + +func getAccessToken(code string) ([]byte, error) { + // 创建HTTP请求 + req, err := http.NewRequest("POST", getAccessTokenUri(code), nil) + if err != nil { + fmt.Printf("http request has some err %v\n", err) + return nil, err + } + // http header添加auth认证信息 + req.Header.Add("Authorization", authInfo()) + + // 发起http请求 + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + fmt.Printf("client do request has some err %v\n", err) + return nil, err + } + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("io read http body has some err %v\n", err) + return nil, err + } + + return respBody, err +} + +// 获取access token +func getAccessTokenUri(code string) string { + return fmt.Sprintf("http://%s:%d/token?grant_type=authorization_code&code=%s&redirect_uri=http://%s:%d/v1/callback", config.ConfigIns().DidServerInfo.Ip, config.ConfigIns().DidServerInfo.Port, code, + config.ConfigIns().DidClientInfo.Ip, config.ConfigIns().HttpPort) +} + +// 添加header认证信息 +func authInfo() string { + basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", config.ConfigIns().DidClientInfo.ClientId, config.ConfigIns().DidClientInfo.Secret))) + return basicAuth +} diff --git a/weidentity-task1/src/did-client/httpx/router.go b/weidentity-task1/src/did-client/httpx/router.go new file mode 100644 index 00000000..de0adad9 --- /dev/null +++ b/weidentity-task1/src/did-client/httpx/router.go @@ -0,0 +1,25 @@ +package httpx + +import ( + "did-client/config" + "fmt" + "github.com/gin-gonic/gin" +) + +// DidOAuthClient represents a did OAuth 2.0 client. +type DidOAuthClient struct { + ClientID string + ClientSecret string +} + +func Run() error { + r := gin.Default() + didR := r.Group("v1") + { + didR.GET("loginWithDid", loginWithDid) + didR.GET("callback", callback) + didR.GET("loginWithCode", loginWithCode) + } + + return r.Run(fmt.Sprintf(":%d", config.ConfigIns().HttpPort)) +} diff --git a/weidentity-task1/src/did-client/main.go b/weidentity-task1/src/did-client/main.go new file mode 100644 index 00000000..dd84a3e6 --- /dev/null +++ b/weidentity-task1/src/did-client/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "did-client/httpx" + "fmt" +) + +func main() { + fmt.Printf("=== Welcome To DID Oauth 2.0 Client ===\n") + err := httpx.Run() + if err != nil { + fmt.Printf("start oatuh client has some err %v\n", err) + return + } +} diff --git a/weidentity-task1/src/did-client2/README.md b/weidentity-task1/src/did-client2/README.md new file mode 100644 index 00000000..033320e4 --- /dev/null +++ b/weidentity-task1/src/did-client2/README.md @@ -0,0 +1,53 @@ +# did client + +did-client的代码实现了整个项目架构中的业务系统,基于go语言(go 1.20)实现,通过`gin`框架实现http服务。 + +## 项目结构 + +代码目录结构如下: + +```shell +├── README.md +├── config +│   └── config.go +├── config.yaml +├── go.mod +├── go.sum +├── httpx +│   ├── handler.go +│   └── router.go +└── main.go +``` +- httpx: 对外提供http服务,供前端调用,router是具体的路由方法,handler是对应的实现; +- config:配置管理功能,读取`config.yaml`文件,该文件中有各配置项的说明; +- main.go: 方法入口。 + +## api接口 + +该客户端提供的主要接口。 + +1. loginWithDid did登录接口 + + 该接口调用后跳转到did登录的认证服务,登录成功后,did认证服务会返回code码。 + +2. callback 回调接口 + + 该接口将`loginWithDid`中获取到的code拼接到url上,并重定向至前端地址,该步骤是为了把code传给前端页面。 + +3. loginWithCode 根据code调用中心系统接口获取token + + 该接口通过调用完成code换取token的步骤。 + +## 使用方式 + +简单介绍系统如何编译和运行。 + +### 启动服务 + +```shell +# 确保系统已经安装go环境 +export GOPROXY="https://goproxy.cn" +export GO111MODULE="on" +export CONF_PATH=./conf_file +go run main.go +``` diff --git a/weidentity-task1/src/did-client2/conf_file/config.yaml b/weidentity-task1/src/did-client2/conf_file/config.yaml new file mode 100644 index 00000000..f9f2fa00 --- /dev/null +++ b/weidentity-task1/src/did-client2/conf_file/config.yaml @@ -0,0 +1,17 @@ +# http服务端口 +httpPort: 20001 +# 认证系统信息 +didServerInfo: + ip: "127.0.0.1" + port: 10003 +# did client信息,即在认证系统注册的client信息 +didClientInfo: + ip: "127.0.0.1" + port: 20001 + # 在did中心认证系统注册的clientId和secret + clientId: "did_client_2" + secret: "***REMOVED***" +# 后端获取code成功后,跳转的前端页面地址 +redirectFront: + ip: "127.0.0.1" + port: 10001 \ No newline at end of file diff --git a/weidentity-task1/src/did-client2/config/config.go b/weidentity-task1/src/did-client2/config/config.go new file mode 100644 index 00000000..8f6228e9 --- /dev/null +++ b/weidentity-task1/src/did-client2/config/config.go @@ -0,0 +1,71 @@ +package config + +import ( + "os" + "sync" + + "github.com/spf13/viper" +) + +var ( + once sync.Once + conf *Config +) + +type Config struct { + path string + HttpPort int + DidServerInfo DidServerInfo `yaml:"didServerInfo"` + DidClientInfo DidClientInfo `yaml:"didClientInfo"` + RedirectFront RedirectFront `yaml:"redirectFront"` +} + +type DidServerInfo struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` +} + +type RedirectFront struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` +} + +type DidClientInfo struct { + Ip string `yaml:"ip"` + Port int `yaml:"port"` + ClientId string `yaml:"clientId"` + Secret string `yaml:"secret"` +} + +func ConfigIns() *Config { + return conf +} + +func init() { + once.Do(func() { + conf = new(Config) + }) + + var err error + + conf.path = os.Getenv("CONF_PATH") + if len(conf.path) == 0 { + conf.path, err = os.Getwd() + if err != nil { + panic(err) + } + } + + viper.AddConfigPath(conf.path) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + err = viper.ReadInConfig() + if err != nil { + panic(err) + } + + err = viper.Unmarshal(conf) + if err != nil { + panic(err) + } +} diff --git a/weidentity-task1/src/did-client2/go.mod b/weidentity-task1/src/did-client2/go.mod new file mode 100644 index 00000000..cf0c60b9 --- /dev/null +++ b/weidentity-task1/src/did-client2/go.mod @@ -0,0 +1,45 @@ +module did-client + +go 1.20 + +require ( + github.com/gin-gonic/gin v1.9.1 + github.com/spf13/viper v1.16.0 +) + +require ( + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/weidentity-task1/src/did-client2/go.sum b/weidentity-task1/src/did-client2/go.sum new file mode 100644 index 00000000..2f48f3f1 --- /dev/null +++ b/weidentity-task1/src/did-client2/go.sum @@ -0,0 +1,550 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-github/v37 v37.0.0 h1:rCspN8/6kB1BAJWZfuafvHhyfIo5fkAulaP/3bOQ/tM= +github.com/google/go-github/v37 v37.0.0/go.mod h1:LM7in3NmXDrX58GbEHy7FtNLbI2JijX93RnMKvWG3m4= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/weidentity-task1/src/did-client2/httpx/handler.go b/weidentity-task1/src/did-client2/httpx/handler.go new file mode 100644 index 00000000..7243e193 --- /dev/null +++ b/weidentity-task1/src/did-client2/httpx/handler.go @@ -0,0 +1,116 @@ +package httpx + +import ( + "did-client/config" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/gin-gonic/gin" +) + +type TokenRequest struct { + GrantType string `json:"grant_type"` + Code string `json:"code"` + RedirectUri string `json:"redirect_uri"` +} + +type ThirdClientResp struct { + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + RefreshToken string `json:"refresh_token"` + Scope string `json:"scope"` + TokenType string `json:"token_type"` +} + +// 通过did的方式进行登录 +func loginWithDid(ctx *gin.Context) { + ctx.Redirect(http.StatusSeeOther, loginRedirectUri()) +} + +func loginRedirectUri() string { + return fmt.Sprintf("http://%s:%d/authorize?client_id=%s&response_type=code&scope=all&state=xyz&redirect_uri=http://%s:%d/v1/callback", + config.ConfigIns().DidServerInfo.Ip, config.ConfigIns().DidServerInfo.Port, + config.ConfigIns().DidClientInfo.ClientId, config.ConfigIns().DidClientInfo.Ip, config.ConfigIns().DidClientInfo.Port) +} + +func callback(ctx *gin.Context) { + code := ctx.Query("code") + + fmt.Println(code) + + ctx.Redirect(http.StatusFound, fmt.Sprintf("http://%s:%d/oauth-result?code=%s", config.ConfigIns().RedirectFront.Ip, config.ConfigIns().RedirectFront.Port, code)) +} + +func loginWithCode(ctx *gin.Context) { + code := ctx.Query("code") + + resp, err := getAccessToken(code) + if err != nil { + ctx.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": err.Error(), + }) + ctx.Abort() + return + } + + ret := new(ThirdClientResp) + + err = json.Unmarshal(resp, ret) + if err != nil { + ctx.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": err.Error(), + }) + ctx.Abort() + return + } + + ctx.JSON(http.StatusOK, gin.H{ + "code": 0, + "msg": "success", + "data": ret, + }) +} + +func getAccessToken(code string) ([]byte, error) { + // 创建HTTP请求 + req, err := http.NewRequest("POST", getAccessTokenUri(code), nil) + if err != nil { + fmt.Printf("http request has some err %v\n", err) + return nil, err + } + // http header添加auth认证信息 + req.Header.Add("Authorization", authInfo()) + + // 发起http请求 + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + fmt.Printf("client do request has some err %v\n", err) + return nil, err + } + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("io read http body has some err %v\n", err) + return nil, err + } + + return respBody, err +} + +// 获取access token +func getAccessTokenUri(code string) string { + return fmt.Sprintf("http://%s:%d/token?grant_type=authorization_code&code=%s&redirect_uri=http://%s:%d/v1/callback", config.ConfigIns().DidServerInfo.Ip, config.ConfigIns().DidServerInfo.Port, code, + config.ConfigIns().DidClientInfo.Ip, config.ConfigIns().HttpPort) +} + +// 添加header认证信息 +func authInfo() string { + basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", config.ConfigIns().DidClientInfo.ClientId, config.ConfigIns().DidClientInfo.Secret))) + return basicAuth +} diff --git a/weidentity-task1/src/did-client2/httpx/router.go b/weidentity-task1/src/did-client2/httpx/router.go new file mode 100644 index 00000000..de0adad9 --- /dev/null +++ b/weidentity-task1/src/did-client2/httpx/router.go @@ -0,0 +1,25 @@ +package httpx + +import ( + "did-client/config" + "fmt" + "github.com/gin-gonic/gin" +) + +// DidOAuthClient represents a did OAuth 2.0 client. +type DidOAuthClient struct { + ClientID string + ClientSecret string +} + +func Run() error { + r := gin.Default() + didR := r.Group("v1") + { + didR.GET("loginWithDid", loginWithDid) + didR.GET("callback", callback) + didR.GET("loginWithCode", loginWithCode) + } + + return r.Run(fmt.Sprintf(":%d", config.ConfigIns().HttpPort)) +} diff --git a/weidentity-task1/src/did-client2/main.go b/weidentity-task1/src/did-client2/main.go new file mode 100644 index 00000000..29c8ddbf --- /dev/null +++ b/weidentity-task1/src/did-client2/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "did-client/httpx" + "fmt" +) + +func main() { + fmt.Printf("=== Welcome To DID Oauth 2.0 Client2 ===\n") + err := httpx.Run() + if err != nil { + fmt.Printf("start oatuh client has some err %v\n", err) + return + } +} diff --git a/weidentity-task1/src/did-server/.gitignore b/weidentity-task1/src/did-server/.gitignore new file mode 100644 index 00000000..3599a0ce --- /dev/null +++ b/weidentity-task1/src/did-server/.gitignore @@ -0,0 +1,2 @@ +conf_file/config.yaml +.idea \ No newline at end of file diff --git a/weidentity-task1/src/did-server/README.md b/weidentity-task1/src/did-server/README.md new file mode 100644 index 00000000..869079e6 --- /dev/null +++ b/weidentity-task1/src/did-server/README.md @@ -0,0 +1,212 @@ +# did-server did认证系统 + +did-server是对业务系统进行认证、授权的系统,其核心工作原理是通过用户输入的did和签名信息,从链上获取公钥信息进行验证。 + +该系统需要实现oatuh2.0授权码模式的主要功能,包括:获取授权code、使用code交换token、token校验等功能。 + + +## 项目说明 + +### api接口: + +#### 1. login登录 + +登录功能,服务端生成随机待签名信息(uuid),用户复制该uuid使用私钥签名,将did同签名后信息传到后端,然后根据用户did获取的公钥对签名后的信息进行验签,验签成功则代表登录成功; + +![img.png](assets/img.png) + +**请求方式** + +`POST` `login` + +**参数说明** + +| 参数 |类型| 说明 | +|--------------|-|---------------------------------------------------------------------------------------------------------------| +| username |string| 用户did | +| password |string| 用户使用私钥签名后的值 | + +#### 2. 获取授权code + +授权三方业务系统,成功后会将code返回; + +**请求方式** + +`GET` `/authorize` + +**参数说明** + +|参数|类型| 说明 | +|-|-|--------------------------------------------------------------------------------------------------------------| +|client_id|string| 在oauth2 server注册的client_id,详见配置文件 | +|response_type|string| 固定值:`code` | +|scope|string| 权限范围,如:`str1,str2,str3`,str为配置文件的值 | +|state|string| 表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值 | +|redirect_uri|string| 回调uri,会在后面添加query参数`?code=xxx&state=xxx`,发放的code就在其中 | + +**请求示例** + +```shell +# 业务系统请求 +http://server_ip:server_port/authorize?client_id=clientId&response_type=code&scope=all&state=xyz&redirect_uri=http://client_ip:client_port/callback +# 302跳转,返回code +http://client_ip:client_port/callback?code=XUNKO4OPPROWAPFKEWNZWA&state=xyz +``` + +#### 3. 使用`code`交换`token` + +根据请求者的信息,验证成功后,返回token等相关信息; + +**请求方式** + +`POST` `/token` + +**请求头 Authorization** + +- basic auth +- username: `client_id` +- password: `client_secret` + +**Header** +`Content-Type: application/x-www-form-urlencoded` + +**Body参数说明** + +|参数|类型| 说明 | +|-|-|-------------------------| +|grant_type|string| 固定值`authorization_code` | +|code|string| 2 发放的code | +|redirect_uri|string| 2 填写的redirect_uri | + +**Response返回示例** + +```json +{ + "access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyMjIyMjIiLCJleHAiOjE1ODU3MTU1NTksInN1YiI6InRlc3QifQ.ZMgIDQMW7FGxbF1V8zWOmEkmB7aLH1suGYjhDdrT7aCYMEudWUoiCkWHSvBmJahGm0RDXa3IyDoGFxeMfzlDNQ", + "expires_in": 7200, + "refresh_token": "JG7_WGLWXUOW2KV2VLJKSG", + "scope": "all", + "token_type": "Bearer" +} +``` + +### 目录结构 + +代码目录结构如下: +```shell +./ +├── Dockerfile +├── LICENSE +├── README.md +├── README_old.md +├── config +│   ├── app.go +│   ├── config.go +│   └── utils.go +├── config.yaml +├── did +│   ├── logic.go +│   └── model.go +├── go.mod +├── go.sum +├── main.go +├── pkg +│   ├── key +│   │   ├── key.go +│   │   ├── key_test.go +│   │   └── pub.key +│   └── session +│   └── session.go +├── server +│   ├── handler.go +│   ├── oauth.go +│   └── router.go +├── static +│   └── icon +│   ├── bootstrap-solid.svg +│   └── feather.svg +└── tpl + ├── error.html + └── login.html +``` + +- config:配置管理模块; +- config.yaml: 实际的配置文件内容; +- did:封装 `WeIdentity-Rest-Service` 的getWeIdDocument接口,通过did获取did doc; +- pkg:服务主要依赖包,包括验签、生成hash值、通过big Int导出公钥及session增删改查等功能; +- server: oauth的核心功能,包括 `authorize`、`token`、`login`等接口; +- tpl、static:前端的html页面及资源存储目录。 + +### 涉及技术 + +1. oatuh2.0协议的封装,基于 `github.com/go-oauth2/oauth2/v4` 包进行封装,完成oauth协议的主要功能; +2. http服务,基于 `github.com/gin-gonic/gin` 包进行封装,完成http服务的提供; +3. 密钥,基于 `crypto`、`go-ethereum/crypto` 等包进行封装。 + +### 如何运行? + +1. 修改配置文件,标准配置文件如下: +```yaml +# 服务运行的http端口 +httpPort: 10003 +# session 相关配置 +session: + name: session_id + secret_key: "kkoiybh1ah6rbh0" + # 过期时间 + # 单位秒 + # 默认20分钟 + max_age: 1200 +# oauth2 相关配置 +oauth2: + # access_token 过期时间 + # 单位小时 + # 默认2小时 + access_token_exp: 30 + # 签名 jwt access_token 时所用 key + jwt_signed_key: "k2bjI75JJHolp0i" + # oauth2 客户端配置 + # 数组类型 + # 可配置多客户端,这里要与业务系统(did-client目录)中的client id和secret一致 + client: + # 客户端id 必须全局唯一 + - id: did_client_1 + # 客户端 secret + secret: "***REMOVED***" + # 应用名 在页面上必要时进行显示 + name: did应用 + # 客户端 domain + # !!注意 http/https 不要写错!! + domain: http://127.0.0.1:20000 + # 权限范围 + # 颁发的 access_token 中会包含该值 资源方可以对该值进行验证 + scope: + # 权限范围 id 唯一 + - id: all + # 权限范围名称 + title: "用户账号、手机、权限、角色等信息" + - id: did_client_2 + secret: "***REMOVED***" + name: did应用2 + domain: http://127.0.0.1:20001 + scope: + - id: all + title: "用户账号、手机、权限、角色等信息" +# WeIdentity-Rest-Service +didServer: + ip: "192.168.0.95" + port: "6001" +``` + +将配置文件中涉及到的ip和port等信息,修改为你部署的地址,例如 `didServer`配置项的修改。 + +2. 直接编译运行 + +```shell +# 请确保已经安装go环境 +export GOPROXY="https://goproxy.cn" +export GO111MODULE="on" +export CONF_PATH=./conf_file +go run main.go +``` + diff --git a/weidentity-task1/src/did-server/assets/img.png b/weidentity-task1/src/did-server/assets/img.png new file mode 100644 index 00000000..9dd35140 Binary files /dev/null and b/weidentity-task1/src/did-server/assets/img.png differ diff --git a/weidentity-task1/src/did-server/config/app.go b/weidentity-task1/src/did-server/config/app.go new file mode 100644 index 00000000..82801ead --- /dev/null +++ b/weidentity-task1/src/did-server/config/app.go @@ -0,0 +1,36 @@ +package config + +type App struct { + path string `yaml:"path"` + HttpPort int `yaml:"httpPort"` + Session struct { + Name string `yaml:"name"` + SecretKey string `yaml:"secret_key"` + MaxAge int `yaml:"max_age"` + } `yaml:"session"` + + OAuth2 struct { + AccessTokenExp int `yaml:"access_token_exp"` + JWTSignedKey string `yaml:"jwt_signed_key"` + Client []OAuth2Client `yaml:"client"` + } `yaml:"oauth2"` + DidServer DidServer `yaml:"didServer"` +} + +type OAuth2Client struct { + ID string `yaml:"id"` + Secret string `yaml:"secret"` + Name string `yaml:"name"` + Domain string `yaml:"domain"` + Scope []Scope `yaml:"scope"` +} + +type Scope struct { + ID string `yaml:"id"` + Title string `yaml:"title"` +} + +type DidServer struct { + Ip string `json:"ip"` + Port string `json:"port"` +} diff --git a/weidentity-task1/src/did-server/config/config.go b/weidentity-task1/src/did-server/config/config.go new file mode 100644 index 00000000..4fb4dd66 --- /dev/null +++ b/weidentity-task1/src/did-server/config/config.go @@ -0,0 +1,53 @@ +package config + +import ( + "github.com/spf13/viper" + "os" + "sync" +) + +var ( + once sync.Once + conf *App +) + +func Setup() { + once.Do(func() { + conf = new(App) + }) + + var err error + + conf.path = os.Getenv("CONF_PATH") + if len(conf.path) == 0 { + conf.path, err = os.Getwd() + if err != nil { + panic(err) + } + } + + viper.AddConfigPath(conf.path) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + err = viper.ReadInConfig() + if err != nil { + panic(err) + } + + err = viper.Unmarshal(conf) + if err != nil { + panic(err) + } +} + +func Instance() *App { + return conf +} + +func DIdServerIp() string { + return conf.DidServer.Ip +} + +func DIdServerPort() string { + return conf.DidServer.Port +} diff --git a/weidentity-task1/src/did-server/config/utils.go b/weidentity-task1/src/did-server/config/utils.go new file mode 100644 index 00000000..b19c8d8e --- /dev/null +++ b/weidentity-task1/src/did-server/config/utils.go @@ -0,0 +1,42 @@ +package config + +import ( + // "fmt" + "strings" +) + +func Get() *App { + return conf +} + +func GetOAuth2Client(clientID string) (cli OAuth2Client) { + for _, v := range conf.OAuth2.Client { + if v.ID == clientID { + cli = v + } + } + + return +} + +func ScopeJoin(scope []Scope) string { + var s []string + for _, sc := range scope { + s = append(s, sc.ID) + } + return strings.Join(s, ",") +} + +func ScopeFilter(clientID string, scope string) (s []Scope) { + cli := GetOAuth2Client(clientID) + sl := strings.Split(scope, ",") + for _, str := range sl { + for _, sc := range cli.Scope { + if str == sc.ID { + s = append(s, sc) + } + } + } + + return +} diff --git a/weidentity-task1/src/did-server/did/logic.go b/weidentity-task1/src/did-server/did/logic.go new file mode 100644 index 00000000..894e0840 --- /dev/null +++ b/weidentity-task1/src/did-server/did/logic.go @@ -0,0 +1,80 @@ +package did + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "io" + "net/http" +) + +// GetWeIdDocument 通过请求did获取did doc,进而获取公钥信息 +func GetWeIdDocument(restServerIp string, restServerPort string, weid string) (WeIdDocumentInvokeResponse, error) { + funcName := "getWeIdDocument" + invokeResponseStr, err := consumeGetWeIdDocumentInvokeRestApi(restServerIp, restServerPort, funcName, weid) + if err != nil { + return WeIdDocumentInvokeResponse{}, err + } + + weIdDocumentInvokeResponse, err := convertJsonToWeIdDocumentInvokeResponse(invokeResponseStr) + if err != nil { + return WeIdDocumentInvokeResponse{}, err + } + + if weIdDocumentInvokeResponse.ErrorCode != 0 { + return WeIdDocumentInvokeResponse{}, errors.New(weIdDocumentInvokeResponse.ErrorMessage) + } + return weIdDocumentInvokeResponse, nil +} + +func consumeGetWeIdDocumentInvokeRestApi(restServerIp string, restServerPort string, funcName string, weid string) (string, error) { + url := getUrl(restServerIp, restServerPort, "invoke") + + jsonB := bytes.Buffer{} + jsonB.WriteString(`{"functionArg": {"weId": "`) + jsonB.WriteString(weid) + jsonB.WriteString(`"}, "transactionArg": {}, "functionName": "`) + jsonB.WriteString(funcName) + jsonB.WriteString(`","v": "1.0.0"}`) + + response, err := consumeRestApi(url, jsonB.String()) + return response, err +} + +func consumeRestApi(url string, json string) (string, error) { + jsonBytes := []byte(json) + response, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBytes)) + if err != nil { + fmt.Printf("The Http request failed with error %s\n", err) + return "", err + } + data, err := io.ReadAll(response.Body) + if err != nil { + return "", err + } + return string(data), nil +} + +func getUrl(restServerIp string, restServerPort string, mappingType string) string { + url := bytes.Buffer{} + url.WriteString("http://") + url.WriteString(restServerIp) + url.WriteString(":") + url.WriteString(restServerPort) + url.WriteString("/weid/api/") + url.WriteString(mappingType) + fmt.Println(url.String()) + + return url.String() +} + +func convertJsonToWeIdDocumentInvokeResponse(jsonStr string) (WeIdDocumentInvokeResponse, error) { + jsonBytes := []byte(jsonStr) + response := WeIdDocumentInvokeResponse{} + err := json.Unmarshal(jsonBytes, &response) + if err != nil { + return response, err + } + return response, nil +} diff --git a/weidentity-task1/src/did-server/did/model.go b/weidentity-task1/src/did-server/did/model.go new file mode 100644 index 00000000..b5ab02f8 --- /dev/null +++ b/weidentity-task1/src/did-server/did/model.go @@ -0,0 +1,46 @@ +package did + +type WeIdDocumentInvokeResponse struct { + RespBody *WeIdDocumentBody `json:"respBody"` + ErrorCode int `json:"errorCode"` + ErrorMessage string `json:"errorMessage"` +} + +type WeIdDocumentBody struct { + ResolutionMetadata ResolutionMetadata `json:"resolutionMetadata"` + WeIdDocumentJson string `json:"weIdDocumentJson"` + WeIdDocumentMetadata WeIdDocumentMetadata `json:"weIdDocumentMetadata"` +} + +type WeIdDocumentMetadata struct { + Created string `json:"created"` + Updated string `json:"updated"` + Deactivated bool `json:"deactivated"` + VersionId int `json:"versionId"` +} + +type ResolutionMetadata struct { + ContentType string `json:"contentType"` + Error string `json:"error"` +} + +type WeIdDocumentJson struct { + Context string // doc 上下文 + Id string `json:"id"` // weid doc的唯一id + Authentication []AuthenticationStruct `json:"authentication"` // 断言结构 + Service []ServiceStruct `json:"service"` // 服务端点 +} + +type AuthenticationStruct struct { + Id string + Type string + Controller string + PublicKeyMultibase string + PublicKey string +} + +type ServiceStruct struct { + Id string `json:"id"` + Type string `json:"type"` + ServiceEndpoint string `json:"serviceEndpoint"` +} diff --git a/weidentity-task1/src/did-server/go.mod b/weidentity-task1/src/did-server/go.mod new file mode 100644 index 00000000..f2880ce7 --- /dev/null +++ b/weidentity-task1/src/did-server/go.mod @@ -0,0 +1,66 @@ +module did-server + +go 1.20 + +require ( + github.com/ethereum/go-ethereum v1.13.1 + github.com/gin-gonic/gin v1.9.1 + github.com/go-oauth2/oauth2/v4 v4.4.2 + github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/google/uuid v1.3.0 + github.com/gorilla/sessions v1.2.1 + github.com/pkg/errors v0.9.1 + github.com/spf13/viper v1.17.0 + golang.org/x/crypto v0.13.0 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.10.0 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tidwall/btree v0.0.0-20191029221954-400434d76274 // indirect + github.com/tidwall/buntdb v1.1.2 // indirect + github.com/tidwall/gjson v1.12.1 // indirect + github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e // indirect + github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.15.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/weidentity-task1/src/did-server/go.sum b/weidentity-task1/src/did-server/go.sum new file mode 100644 index 00000000..f1caf9a1 --- /dev/null +++ b/weidentity-task1/src/did-server/go.sum @@ -0,0 +1,665 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.13.1 h1:UF2FaUKPIy5jeZk3X06ait3y2Q4wI+vJ1l7+UARp+60= +github.com/ethereum/go-ethereum v1.13.1/go.mod h1:xHQKzwkHSl0gnSjZK1mWa06XEdm9685AHqhRknOzqGQ= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-oauth2/oauth2/v4 v4.4.2 h1:tWQlR5I4/qhWiyOME67BAFmo622yi+2mm7DMm8DpMdg= +github.com/go-oauth2/oauth2/v4 v4.4.2/go.mod h1:K4DemYzNwwYnIDOPdHtX/7SlO0AHdtlphsTgE7lA3PA= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/btree v0.0.0-20191029221954-400434d76274 h1:G6Z6HvJuPjG6XfNGi/feOATzeJrfgTNJY+rGrHbA04E= +github.com/tidwall/btree v0.0.0-20191029221954-400434d76274/go.mod h1:huei1BkDWJ3/sLXmO+bsCNELL+Bp2Kks9OLyQFkzvA8= +github.com/tidwall/buntdb v1.1.2 h1:noCrqQXL9EKMtcdwJcmuVKSEjqu1ua99RHHgbLTEHRo= +github.com/tidwall/buntdb v1.1.2/go.mod h1:xAzi36Hir4FarpSHyfuZ6JzPJdjRZ8QlLZSntE2mqlI= +github.com/tidwall/gjson v1.3.4/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo= +github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb h1:5NSYaAdrnblKByzd7XByQEJVT8+9v0W/tIY0Oo4OwrE= +github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb/go.mod h1:lKYYLFIr9OIgdgrtgkZ9zgRxRdvPYsExnYBsEAd8W5M= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e h1:+NL1GDIUOKxVfbp2KoJQD9cTQ6dyP2co9q4yzmT9FZo= +github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e/go.mod h1:/h+UnNGt0IhNNJLkGikcdcJqm66zGD/uJGMRxK/9+Ao= +github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 h1:Otn9S136ELckZ3KKDyCkxapfufrqDqwmGjcHfAyXRrE= +github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563/go.mod h1:mLqSmt7Dv/CNneF2wfcChfN1rvapyQr01LGKnKex0DQ= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A= +github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/weidentity-task1/src/did-server/main.go b/weidentity-task1/src/did-server/main.go new file mode 100644 index 00000000..242ce838 --- /dev/null +++ b/weidentity-task1/src/did-server/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "did-server/config" + "did-server/pkg/session" + "did-server/server" + "log" +) + +func main() { + // 配置文件初始化 + config.Setup() + + // session 初始化 + session.Setup() + + err := server.Run() + if err != nil { + log.Fatalln(err) + } +} diff --git a/weidentity-task1/src/did-server/pkg/key/key.go b/weidentity-task1/src/did-server/pkg/key/key.go new file mode 100644 index 00000000..b389e275 --- /dev/null +++ b/weidentity-task1/src/did-server/pkg/key/key.go @@ -0,0 +1,58 @@ +package key + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "github.com/ethereum/go-ethereum/crypto/secp256k1" + "golang.org/x/crypto/sha3" + "math/big" +) + +// hash待签名信息 +func Hash(msg []byte) []byte { + h := sha3.NewLegacyKeccak256() + h.Write(msg) + return h.Sum(nil) +} + +// 传入公钥,校验公钥对应私钥的签名信息 +func VerifySignature(msg []byte, signedMsg []byte, publicKeyBytes []byte) bool { + signatureNoRecoverID := signedMsg[:len(signedMsg)-1] + return secp256k1.VerifySignature(publicKeyBytes, msg, signatureNoRecoverID) +} + +// 通过公钥的X推出公钥的字节数组 +func ConvertPublicKeyBigIntToPublicBytes(pubBigInt string) []byte { + publicKeyInt := new(big.Int) + publicKeyInt.SetString(pubBigInt, 10) + curve := secp256k1.S256() + + pubKey := &ecdsa.PublicKey{ + Curve: curve, + X: publicKeyInt, + Y: deriveY(publicKeyInt, curve), + } + + return elliptic.MarshalCompressed(secp256k1.S256(), pubKey.X, pubKey.Y) +} + +// 通过椭圆曲线算法类型和X计算Y +func deriveY(x *big.Int, curve *secp256k1.BitCurve) *big.Int { + // 计算 y^2 = x^3 + ax + b + x3 := new(big.Int).Mul(x, x) + x3.Mul(x3, x) + a := curve.Params().P + b := curve.Params().B + y2 := new(big.Int).Add(x3, new(big.Int).Mul(a, x)) + y2.Add(y2, b) + + // 计算 y = sqrt(y^2) + y := new(big.Int).ModSqrt(y2, curve.Params().P) + + // 如果 y 的奇偶性与公钥的标志位不一致,则需要取反 y + if y.Bit(0) != x.Bit(0) { + y.Sub(curve.Params().P, y) + } + + return y +} diff --git a/weidentity-task1/src/did-server/pkg/key/key_test.go b/weidentity-task1/src/did-server/pkg/key/key_test.go new file mode 100644 index 00000000..263581aa --- /dev/null +++ b/weidentity-task1/src/did-server/pkg/key/key_test.go @@ -0,0 +1,54 @@ +package key + +import ( + "encoding/base64" + "math/big" + "os" + "testing" +) + +func TestConvertToPubAndVerify(t *testing.T) { + //pub := "112028570508690591160769248348403126748000109039375280547090697478051580518976" + //pub := "56324583500139157107793773182419696027958188324056843006630313992576092448359" + pub := "18842764861699425946864317179718860321130262798130268203739550375195125305295" + //18842764861699425946864317179718860321130262798130268203739550375195125305295 + + publicKeyBytes := ConvertPublicKeyBigIntToPublicBytes(pub) + + //pubPath := "./pub.key" + //publicKeyBytes, err := os.ReadFile(pubPath) + //if err != nil { + // t.Error(err) + // return + //} + + msg := "hello world" + signMsg := "vWh1Yhu2ZwTOlsGMHbcPSwb2s2VMMRR8kWqU5UPGhyIlrbN7hSw23WQGq2IC1kWJ2qTV4A9Mi7x9SWuWEOgG0gE=" + + signedMsgBytes, err := base64.StdEncoding.DecodeString(signMsg) + if err != nil { + t.Error(err) + return + } + + yes := VerifySignature(Hash([]byte(msg)), signedMsgBytes, publicKeyBytes) + + if yes { + t.Log("verify success...") + } else { + t.Log("verify failed...") + } +} + +func TestHandlePublicKey(t *testing.T) { + pubPath := "./pub.key" + pubBytes, err := os.ReadFile(pubPath) + if err != nil { + t.Error(err) + return + } + + publicKeyBigInt := new(big.Int).SetBytes(pubBytes[1:]) + + t.Log(publicKeyBigInt.String()) +} diff --git a/weidentity-task1/src/did-server/pkg/session/session.go b/weidentity-task1/src/did-server/pkg/session/session.go new file mode 100644 index 00000000..794e924f --- /dev/null +++ b/weidentity-task1/src/did-server/pkg/session/session.go @@ -0,0 +1,66 @@ +package session + +import ( + // "log" + "encoding/gob" + "net/http" + "net/url" + + "github.com/gorilla/sessions" + // "gopkg.in/boj/redistore.v1" + + "did-server/config" +) + +var store *sessions.CookieStore + +func Setup() { + gob.Register(url.Values{}) + + store = sessions.NewCookieStore([]byte(config.Get().Session.SecretKey)) + store.Options = &sessions.Options{ + Path: "/", + // session 有效期 + // 单位秒 + MaxAge: config.Get().Session.MaxAge, + HttpOnly: true, + } +} + +func Get(r *http.Request, name string) (val interface{}, err error) { + // Get a session. + session, err := store.Get(r, config.Get().Session.Name) + if err != nil { + return + } + + val = session.Values[name] + + return +} + +func Set(w http.ResponseWriter, r *http.Request, name string, val interface{}) (err error) { + // Get a session. + session, err := store.Get(r, config.Get().Session.Name) + if err != nil { + return + } + + session.Values[name] = val + err = session.Save(r, w) + + return +} + +func Delete(w http.ResponseWriter, r *http.Request, name string) (err error) { + // Get a session. + session, err := store.Get(r, config.Get().Session.Name) + if err != nil { + return + } + + delete(session.Values, name) + err = session.Save(r, w) + + return +} diff --git a/weidentity-task1/src/did-server/server/handler.go b/weidentity-task1/src/did-server/server/handler.go new file mode 100644 index 00000000..395e6294 --- /dev/null +++ b/weidentity-task1/src/did-server/server/handler.go @@ -0,0 +1,213 @@ +package server + +import ( + "did-server/config" + "did-server/did" + "did-server/pkg/key" + "did-server/pkg/session" + "encoding/base64" + "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/pkg/errors" + "html/template" + "net/http" + "net/url" + "time" +) + +const ( + signedMsgFileName = "signedMsg.txt" +) + +var msgInfo string + +// 验证client +func authorize(ctx *gin.Context) { + w := ctx.Writer + r := ctx.Request + + var form url.Values + if v, _ := session.Get(r, "RequestForm"); v != nil { + r.ParseForm() + if len(r.Form.Get("client_id")) == 0 { + form = v.(url.Values) + } + } + r.Form = form + + if err := session.Delete(w, r, "RequestForm"); err != nil { + errorHandler(w, err.Error(), http.StatusInternalServerError) + return + } + + if err := srv.HandleAuthorizeRequest(w, r); err != nil { + + fmt.Println(err) + + errorHandler(w, err.Error(), http.StatusBadRequest) + return + } +} + +type TplData struct { + Client config.OAuth2Client + // 用户申请的合规scope + Scope []config.Scope + Error string + SignMsg string `json:"signMsg"` +} + +type GenSignMsgRequest struct { + Did string `json:"did"` +} + +// 登录 +func login(ctx *gin.Context) { + w := ctx.Writer + r := ctx.Request + form, _ := session.Get(r, "RequestForm") + if form == nil { + errorHandler(w, "无效的请求", http.StatusInternalServerError) + return + } + clientID := form.(url.Values).Get("client_id") + + if r.Method != "POST" { + // 页面数据 + data := TplData{ + Client: config.GetOAuth2Client(clientID), + SignMsg: genMsg(), + } + + t, _ := template.ParseFiles("tpl/login.html") + t.Execute(w, data) + } else if r.Method == "POST" { + var ( + weDid string + err error + ) + + if r.Form == nil { + err = r.ParseForm() + if err != nil { + errorHandler(w, err.Error(), http.StatusInternalServerError) + return + } + } + + weDid, err = Authentication(r.Form.Get("username"), r.Form.Get("password")) + if err != nil { + // 页面数据 + data := TplData{ + Client: config.GetOAuth2Client(clientID), + SignMsg: genMsg(), + Error: err.Error(), + } + data.Error = err.Error() + t, _ := template.ParseFiles("tpl/login.html") + t.Execute(w, data) + return + } + + err = session.Set(w, r, "LoggedInUserID", weDid) + if err != nil { + errorHandler(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Location", "/authorize") + w.WriteHeader(http.StatusFound) + return + } +} + +// 生成每次登录验证的待签名信息 +func genMsg() string { + msgInfo = uuid.NewString() + return msgInfo +} + +// 验证用户登录信息 +func Authentication(username string, signedMsg string) (string, error) { + pubBytes, err := getPublicKeyBytesByDid(username) + if err != nil { + fmt.Printf("get public key by did has some err %v\n", err) + return "", err + } + + signedMsgBytes, err := base64.StdEncoding.DecodeString(signedMsg) + if err != nil { + fmt.Printf("decode string has some err %v\n", err) + return "", err + } + + success := key.VerifySignature(key.Hash([]byte(msgInfo)), signedMsgBytes, pubBytes) + if !success { + return "", errors.New("verify signature has some err") + } + + return username, nil +} + +// 生成access token +func token(ctx *gin.Context) { + w := ctx.Writer + r := ctx.Request + err := srv.HandleTokenRequest(w, r) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +// 通过did获取公钥信息 +func getPublicKeyBytesByDid(weid string) ([]byte, error) { + resp, err := did.GetWeIdDocument(config.DIdServerIp(), config.DIdServerPort(), weid) + if err != nil { + return nil, err + } + + weidDocJson := new(did.WeIdDocumentJson) + err = json.Unmarshal([]byte(resp.RespBody.WeIdDocumentJson), weidDocJson) + if err != nil { + return nil, err + } + + if len(weidDocJson.Authentication) != 1 { + return nil, errors.New("user pub amount is not correct.") + } + + fmt.Println(weidDocJson.Authentication[0].PublicKey) + + pubBytes := key.ConvertPublicKeyBigIntToPublicBytes(weidDocJson.Authentication[0].PublicKey) + + return pubBytes, nil +} + +// 校验access token +func verify(ctx *gin.Context) { + w := ctx.Writer + r := ctx.Request + tokenInfo, err := srv.ValidationBearerToken(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + cli, err := mgr.GetClient(r.Context(), tokenInfo.GetClientID()) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + data := map[string]interface{}{ + "expires_in": int64(tokenInfo.GetAccessCreateAt().Add(tokenInfo.GetAccessExpiresIn()).Sub(time.Now()).Seconds()), + "user_id": tokenInfo.GetUserID(), + "client_id": tokenInfo.GetClientID(), + "scope": tokenInfo.GetScope(), + "domain": cli.GetDomain(), + } + e := json.NewEncoder(w) + e.SetIndent("", " ") + e.Encode(data) +} diff --git a/weidentity-task1/src/did-server/server/oauth.go b/weidentity-task1/src/did-server/server/oauth.go new file mode 100644 index 00000000..4d2a4504 --- /dev/null +++ b/weidentity-task1/src/did-server/server/oauth.go @@ -0,0 +1,119 @@ +package server + +import ( + "did-server/config" + "did-server/pkg/session" + "github.com/go-oauth2/oauth2/v4/errors" + "github.com/go-oauth2/oauth2/v4/generates" + "github.com/go-oauth2/oauth2/v4/manage" + "github.com/go-oauth2/oauth2/v4/models" + "github.com/go-oauth2/oauth2/v4/server" + "github.com/go-oauth2/oauth2/v4/store" + "github.com/golang-jwt/jwt" + "html/template" + "log" + "net/http" + "time" +) + +var srv *server.Server +var mgr *manage.Manager + +func InitOauth() { + // manager config + mgr = manage.NewDefaultManager() + mgr.SetAuthorizeCodeTokenCfg(&manage.Config{ + AccessTokenExp: time.Minute * 30, + RefreshTokenExp: time.Minute * 30, + IsGenerateRefresh: true}) + // token store + mgr.MustTokenStorage(store.NewMemoryTokenStore()) + + // access token generate method: jwt + mgr.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte(config.Get().OAuth2.JWTSignedKey), jwt.SigningMethodHS512)) + + clientStore := store.NewClientStore() + for _, v := range config.Get().OAuth2.Client { + clientStore.Set(v.ID, &models.Client{ + ID: v.ID, + Secret: v.Secret, + Domain: v.Domain, + }) + } + + mgr.MapClientStorage(clientStore) + // config oauth2 server + srv = server.NewServer(server.NewConfig(), mgr) + srv.SetPasswordAuthorizationHandler(passwordAuthorizationHandler) + srv.SetUserAuthorizationHandler(userAuthorizeHandler) + srv.SetAuthorizeScopeHandler(authorizeScopeHandler) + srv.SetInternalErrorHandler(internalErrorHandler) + srv.SetResponseErrorHandler(responseErrorHandler) +} + +func passwordAuthorizationHandler(username, password string) (string, error) { + return Authentication(username, password) +} + +func userAuthorizeHandler(w http.ResponseWriter, r *http.Request) (string, error) { + v, _ := session.Get(r, "LoggedInUserID") + if v == nil { + if r.Form == nil { + r.ParseForm() + } + session.Set(w, r, "RequestForm", r.Form) + + // 登录页面 + // 最终会把userId写进session(LoggedInUserID) + // 再跳回来 + w.Header().Set("Location", "/login") + w.WriteHeader(http.StatusFound) + + return "", nil + } + // 不记住用户 + // store.Delete("LoggedInUserID") + // store.Save() + + return v.(string), nil +} + +// 场景:在登录页面勾选所要访问的资源范围 +// 根据client注册的scope,过滤表单中非法scope +// HandleAuthorizeRequest中调用 +// set scope for the access token +func authorizeScopeHandler(w http.ResponseWriter, r *http.Request) (scope string, err error) { + if r.Form == nil { + r.ParseForm() + } + s := config.ScopeFilter(r.Form.Get("client_id"), r.Form.Get("scope")) + if s == nil { + err = errors.New("无效的权限范围") + return + } + scope = config.ScopeJoin(s) + return +} + +func internalErrorHandler(err error) (re *errors.Response) { + log.Println("Internal Error:", err.Error()) + return +} + +func responseErrorHandler(re *errors.Response) { + log.Println("Response Error:", re.Error.Error()) +} + +// 错误显示页面 +// 以网页的形式展示大于400的错误 +func errorHandler(w http.ResponseWriter, message string, status int) { + w.WriteHeader(status) + if status >= 400 { + t, _ := template.ParseFiles("tpl/error.html") + body := struct { + Status int + Message string + }{Status: status, Message: message} + t.Execute(w, body) + } +} diff --git a/weidentity-task1/src/did-server/server/router.go b/weidentity-task1/src/did-server/server/router.go new file mode 100644 index 00000000..53599b75 --- /dev/null +++ b/weidentity-task1/src/did-server/server/router.go @@ -0,0 +1,35 @@ +package server + +import ( + "did-server/config" + "fmt" + "github.com/gin-gonic/gin" + "net/http" +) + +// DidOAuthClient represents a did OAuth 2.0 client. +type DidOAuthClient struct { + ClientID string + ClientSecret string +} + +func Run() error { + InitOauth() + r := gin.Default() + didR := r.Group("") + { + didR.GET("authorize", authorize) + didR.Any("login", login) + didR.POST("token", token) + didR.GET("test", Test) + } + + return r.Run(fmt.Sprintf(":%d", config.Instance().HttpPort)) +} + +func Test(ctx *gin.Context) { + ctx.JSON(http.StatusOK, gin.H{ + "msg": "ok", + "code": 0, + }) +} diff --git a/weidentity-task1/src/did-server/static/icon/bootstrap-solid.svg b/weidentity-task1/src/did-server/static/icon/bootstrap-solid.svg new file mode 100644 index 00000000..2f536b68 --- /dev/null +++ b/weidentity-task1/src/did-server/static/icon/bootstrap-solid.svg @@ -0,0 +1,5 @@ + + Bootstrap + + + diff --git a/weidentity-task1/src/did-server/static/icon/feather.svg b/weidentity-task1/src/did-server/static/icon/feather.svg new file mode 100644 index 00000000..e283b387 --- /dev/null +++ b/weidentity-task1/src/did-server/static/icon/feather.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weidentity-task1/src/did-server/tpl/error.html b/weidentity-task1/src/did-server/tpl/error.html new file mode 100644 index 00000000..bcb24485 --- /dev/null +++ b/weidentity-task1/src/did-server/tpl/error.html @@ -0,0 +1,16 @@ + + + + + + {{.Status}} | 出错了~ + + + +

{{.Status}} | {{.Message}}
+ + \ No newline at end of file diff --git a/weidentity-task1/src/did-server/tpl/login.html b/weidentity-task1/src/did-server/tpl/login.html new file mode 100644 index 00000000..526f2789 --- /dev/null +++ b/weidentity-task1/src/did-server/tpl/login.html @@ -0,0 +1,92 @@ + + + + + + + + + + + Sign In With DID + + + + + +
+
+
+ +
+
+ {{if .Error}} + + {{end}} +
+ +
+ +
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+ +
+
+
...
+
+
+
+
    +
  • {{.Client.Name}} 将获得访问您以下资源的权限: +
      + {{range .Scope}} +
    • {{.Title}}
    • + {{end}} +
    +
  • +
+
{{.SignMsg}}
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/weidentity-task1/src/did-wallet/README.md b/weidentity-task1/src/did-wallet/README.md new file mode 100644 index 00000000..95cbfd38 --- /dev/null +++ b/weidentity-task1/src/did-wallet/README.md @@ -0,0 +1,112 @@ +# did-wallet did钱包 + +did-wallet即用户钱包功能,用户可以通过该钱包申请公私钥和weid信息。这里采用go实现,并且通过命令行的方式对外提供功能。 + +## 功能简介 + +- 目录 + +```shell +├── README.md +├── go.mod +├── go.sum +├── logic +│   ├── crypto.go +│   ├── model.go +│   └── weid.go +└── main.go +``` + +- 核心代码 + did-wallet目前核心功能在logic包下面进行实现,`crypto.go`、`weid.go`包实现了关于密钥和weid的核心功能,主要代码如下: + +crypto.go + +```go +func GenerateKeyPair() (publicKeyBytes []byte, privateKeyBytes []byte, publicKeyBigInt *big.Int, privateKeyBigInt *big.Int) { + key, err := ecdsa.GenerateKey(secp256k1.S256(), rand.Reader) + if err != nil { + panic(err) + } + + publicKeyBytes = elliptic.MarshalCompressed(secp256k1.S256(), key.X, key.Y) + publicKeyBigInt = new(big.Int).SetBytes(publicKeyBytes[1:]) + privateKeyBytes = convertPrivateKeyBigIntToPrivateKeyBytes(key.D) + return publicKeyBytes, privateKeyBytes, publicKeyBigInt, key.D +} + +func convertPrivateKeyBigIntToPrivateKeyBytes(privateKeyBigInt *big.Int) []byte { + privateKeyBytes := make([]byte, 32) + blob := privateKeyBigInt.Bytes() + copy(privateKeyBytes[32-len(blob):], blob) + return privateKeyBytes +} +``` + +weid.go + +```go +// CreateWeId 传入公钥和私钥,创建weid +func CreateWeId(serverIp, port string, pubBytes []byte, privBytes []byte) (string, error) { + funcName := "createWeId" + nonce := generateNonce() + encodeResponseStr, err := consumeCreateWeIdEncodeRestApi(serverIp, port, getPublicBigIntByBytes(pubBytes), nonce, funcName) + if err != nil { + fmt.Printf("create weid has some err %v\n", err) + return "", err + } + + transactResponseStr, err := processEncodeResponse(encodeResponseStr, serverIp, port, funcName, nonce, privBytes) + if err != nil { + fmt.Printf("processEncodeResponse has some err %v\n", err) + return "", err + } + + transactResponse, err := convertJsonToTransactResponseStruct(transactResponseStr) + if err != nil { + fmt.Printf("convertJsonToTransactResponseStruct has some err %v\n", err) + return "", err + } + if transactResponse.ErrorCode != 0 { + fmt.Printf("%#v", transactResponse) + return "", errors.New(transactResponse.ErrorMessage) + } + + return transactResponse.RespBody, nil +} +``` + +1. GenerateKeyPair 方法生成公私钥及其big Int,其他方法调用该方法并将公私钥写到本地文件中; +2. CreateWeId 方法则根据传入的公私钥信息,调用 `WeIdentity-Rest-Service` 接口,生成weid并返回; + +- 使用方式 + +本工具提供3个主要功能: + +1. key: 生成公私钥到本地文件中,默认文件名称为:priv.key、pub.key,分别代表公私钥文件; +2. gendid: 读取公私钥文件,并根据指定接口生成weid; +3. sign: 使用私钥进行签名,并返回base64后的签名信息; + +上述命令详细使用如下: + +```shell +# 编译工具 +go build -o weid-tool +# 生成公私钥 +./weid-tool key +generate private key in ./priv.key +generate public key in ./pub.key +# 生成weid +> ./weid-tool gendid -p "./pub.key" -s "./priv.key" -i "192.168.0.95" -t "6001" +http://192.168.0.95:6001/weid/api/encode +http://192.168.0.95:6001/weid/api/transact +generate weid success: did:weid:1:0xa3877c6c598f96ca69350f33f297ec8bb4afd762 +# 签名 +./weid-tool sign "bf68a343-7db2-4565-99d6-ea545aa53cda" -p ./priv.key +Message: bf68a343-7db2-4565-99d6-ea545aa53cda +Signature: Msuym6gIWXTHxU+bJYkb9u8XqhvNAVcC1LNaKAselF1LViCazW5bZeYnX7Ax1ksfGddu4E4bQ25MgoN0/aupnQA= +``` + +命令详情可以通过: 【命令名称】--help 查看,示例如图: + +![gendid命令说明](./assets/img.png) diff --git a/weidentity-task1/src/did-wallet/assets/img.png b/weidentity-task1/src/did-wallet/assets/img.png new file mode 100644 index 00000000..54841359 Binary files /dev/null and b/weidentity-task1/src/did-wallet/assets/img.png differ diff --git a/weidentity-task1/src/did-wallet/go.mod b/weidentity-task1/src/did-wallet/go.mod new file mode 100644 index 00000000..2e135d62 --- /dev/null +++ b/weidentity-task1/src/did-wallet/go.mod @@ -0,0 +1,19 @@ +module did-wallet + +go 1.21 + +require ( + github.com/ethereum/go-ethereum v1.13.1 + github.com/pkg/errors v0.9.1 + github.com/spf13/cobra v1.7.0 + golang.org/x/crypto v0.12.0 +) + +require ( + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/holiman/uint256 v1.2.3 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/sys v0.11.0 // indirect +) diff --git a/weidentity-task1/src/did-wallet/go.sum b/weidentity-task1/src/did-wallet/go.sum new file mode 100644 index 00000000..02eb6d4a --- /dev/null +++ b/weidentity-task1/src/did-wallet/go.sum @@ -0,0 +1,30 @@ +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/go-ethereum v1.13.1 h1:UF2FaUKPIy5jeZk3X06ait3y2Q4wI+vJ1l7+UARp+60= +github.com/ethereum/go-ethereum v1.13.1/go.mod h1:xHQKzwkHSl0gnSjZK1mWa06XEdm9685AHqhRknOzqGQ= +github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= +github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/weidentity-task1/src/did-wallet/logic/crypto.go b/weidentity-task1/src/did-wallet/logic/crypto.go new file mode 100644 index 00000000..e08d85ba --- /dev/null +++ b/weidentity-task1/src/did-wallet/logic/crypto.go @@ -0,0 +1,41 @@ +package logic + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "github.com/ethereum/go-ethereum/crypto/secp256k1" + "golang.org/x/crypto/sha3" + "math/big" +) + +func GenerateKeyPair() (publicKeyBytes []byte, privateKeyBytes []byte, publicKeyBigInt *big.Int, privateKeyBigInt *big.Int) { + key, err := ecdsa.GenerateKey(secp256k1.S256(), rand.Reader) + if err != nil { + panic(err) + } + + publicKeyBytes = elliptic.MarshalCompressed(secp256k1.S256(), key.X, key.Y) + publicKeyBigInt = new(big.Int).SetBytes(publicKeyBytes[1:]) + privateKeyBytes = convertPrivateKeyBigIntToPrivateKeyBytes(key.D) + return publicKeyBytes, privateKeyBytes, publicKeyBigInt, key.D +} + +func convertPrivateKeyBigIntToPrivateKeyBytes(privateKeyBigInt *big.Int) []byte { + privateKeyBytes := make([]byte, 32) + blob := privateKeyBigInt.Bytes() + copy(privateKeyBytes[32-len(blob):], blob) + return privateKeyBytes +} + +func SignSignature(hashedMsg []byte, privateKeyBytes []byte) ([]byte, error) { + signature, err := secp256k1.Sign(hashedMsg, privateKeyBytes) + return signature, err +} + +// hash待签名信息 +func Hash(msg []byte) []byte { + h := sha3.NewLegacyKeccak256() + h.Write(msg) + return h.Sum(nil) +} diff --git a/weidentity-task1/src/did-wallet/logic/model.go b/weidentity-task1/src/did-wallet/logic/model.go new file mode 100644 index 00000000..94cd5132 --- /dev/null +++ b/weidentity-task1/src/did-wallet/logic/model.go @@ -0,0 +1,19 @@ +package logic + +type TransactResponse struct { + RespBody string + ErrorCode int + ErrorMessage string +} + +type EncodeResponse struct { + RespBody *RespBody + ErrorCode int + ErrorMessage string +} + +type RespBody struct { + BlockLimit string `json:"blockLimit"` + Data string `json:"data"` + EncodedTransaction string `json:"encodedTransaction"` +} diff --git a/weidentity-task1/src/did-wallet/logic/weid.go b/weidentity-task1/src/did-wallet/logic/weid.go new file mode 100644 index 00000000..bca5fbd3 --- /dev/null +++ b/weidentity-task1/src/did-wallet/logic/weid.go @@ -0,0 +1,170 @@ +package logic + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "hash/maphash" + "io" + "math/big" + "math/rand" + "net/http" + "strconv" +) + +// CreateWeId 传入公钥和私钥,创建weid +func CreateWeId(serverIp, port string, pubBytes []byte, privBytes []byte) (string, error) { + funcName := "createWeId" + nonce := generateNonce() + encodeResponseStr, err := consumeCreateWeIdEncodeRestApi(serverIp, port, getPublicBigIntByBytes(pubBytes), nonce, funcName) + if err != nil { + fmt.Printf("create weid has some err %v\n", err) + return "", err + } + + transactResponseStr, err := processEncodeResponse(encodeResponseStr, serverIp, port, funcName, nonce, privBytes) + if err != nil { + fmt.Printf("processEncodeResponse has some err %v\n", err) + return "", err + } + + transactResponse, err := convertJsonToTransactResponseStruct(transactResponseStr) + if err != nil { + fmt.Printf("convertJsonToTransactResponseStruct has some err %v\n", err) + return "", err + } + if transactResponse.ErrorCode != 0 { + fmt.Printf("%#v", transactResponse) + return "", errors.New(transactResponse.ErrorMessage) + } + + return transactResponse.RespBody, nil +} + +func consumeCreateWeIdEncodeRestApi(restServerIp string, restServerPort string, publicKeyBigInt *big.Int, nonce string, funcName string) (string, error) { + url := getUrl(restServerIp, restServerPort, "encode") + + jsonB := bytes.Buffer{} + jsonB.WriteString(`{"functionArg":{"publicKey":"`) + jsonB.WriteString(publicKeyBigInt.String()) + jsonB.WriteString(`"},"functionName":"`) + jsonB.WriteString(funcName) + jsonB.WriteString(`","transactionArg": {"nonce": "`) + jsonB.WriteString(nonce) + jsonB.WriteString(`"},"v":"1.0.0"}`) + //fmt.Println("create weid encode request =", json.String()) + + response, err := consumeRestApi(url, jsonB.String()) + return response, err +} + +func getUrl(restServerIp string, restServerPort string, mappingType string) string { + url := bytes.Buffer{} + url.WriteString("http://") + url.WriteString(restServerIp) + url.WriteString(":") + url.WriteString(restServerPort) + url.WriteString("/weid/api/") + url.WriteString(mappingType) + fmt.Println(url.String()) + + return url.String() +} + +func consumeRestApi(url string, json string) (string, error) { + jsonBytes := []byte(json) + response, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBytes)) + if err != nil { + fmt.Printf("The Http request failed with error %s\n", err) + return "", err + } + data, err := io.ReadAll(response.Body) + if err != nil { + return "", err + } + return string(data), nil +} + +func processEncodeResponse(encodeResponseStr string, restServerIp string, restServerPort string, funcName string, nonce string, privateKeyBytes []byte) (string, error) { + encodeResponse, err := convertJsonToEncodeResponseStruct(encodeResponseStr) + if err != nil { + return "", err + } + if encodeResponse.ErrorCode != 0 { + return "", errors.New(encodeResponse.ErrorMessage) + } + transaction, err := base64.StdEncoding.DecodeString(encodeResponse.RespBody.EncodedTransaction) + if err != nil { + return "", err + } + hashedMsg := Hash(transaction) + signatureBytes, err := SignSignature(hashedMsg, privateKeyBytes) + if err != nil { + return "", err + } + + signatureBase64Str := base64.StdEncoding.EncodeToString(signatureBytes) + transactResponseStr, err := consumeTransactRestApi(restServerIp, restServerPort, signatureBase64Str, encodeResponse.RespBody.Data, nonce, encodeResponse.RespBody.BlockLimit, "2", funcName) + if err != nil { + return "", err + } + return transactResponseStr, nil +} + +func consumeTransactRestApi(restServerIp string, restServerPort string, signature string, data string, nonce, blockLimit, signType string, funcName string) (string, error) { + url := getUrl(restServerIp, restServerPort, "transact") + + jsonB := bytes.Buffer{} + jsonB.WriteString(`{"functionArg":{},"functionName":"`) + jsonB.WriteString(funcName) + jsonB.WriteString(`","transactionArg": {"nonce": "`) + jsonB.WriteString(nonce) + jsonB.WriteString(`","data": "`) + jsonB.WriteString(data) + jsonB.WriteString(`","blockLimit": "`) + jsonB.WriteString(blockLimit) + jsonB.WriteString(`","signType": "`) + jsonB.WriteString(signType) + jsonB.WriteString(`","signedMessage": "`) + jsonB.WriteString(signature) + jsonB.WriteString(`"},"v":"1.0.0"}`) + + response, err := consumeRestApi(url, jsonB.String()) + if err != nil { + fmt.Printf("post transact has some err %v\n", err) + return "", err + } + return response, err +} + +func convertJsonToEncodeResponseStruct(jsonStr string) (EncodeResponse, error) { + jsonBytes := []byte(jsonStr) + response := EncodeResponse{} + err := json.Unmarshal(jsonBytes, &response) + if err != nil { + return response, err + } + return response, nil +} + +func convertJsonToTransactResponseStruct(jsonStr string) (TransactResponse, error) { + jsonBytes := []byte(jsonStr) + response := TransactResponse{} + err := json.Unmarshal(jsonBytes, &response) + if err != nil { + return response, err + } + return response, nil +} + +func generateNonce() string { + r := rand.New(rand.NewSource(int64(new(maphash.Hash).Sum64()))) + nonce := strconv.Itoa(r.Int()) + return nonce +} + +func getPublicBigIntByBytes(pub []byte) *big.Int { + return new(big.Int).SetBytes(pub[1:]) +} diff --git a/weidentity-task1/src/did-wallet/main.go b/weidentity-task1/src/did-wallet/main.go new file mode 100644 index 00000000..91178b51 --- /dev/null +++ b/weidentity-task1/src/did-wallet/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "did-wallet/logic" + "encoding/base64" + "fmt" + "github.com/spf13/cobra" + "os" +) + +var ( + privateKeyPath string + publicKeyPath string + didServiceIp string + didServicePort string +) + +var rootCmd = &cobra.Command{ + Use: "weid-tool", + Short: "weidentity simple tool", + Long: `简易的weid工具,该工具提供weid、公私钥生成、签名等功能`, +} + +// 生成公私钥信息 +var keyCmd = &cobra.Command{ + Use: "key", + Short: "生成公私钥对、weid", + Long: `生成公私钥对、weid,并将生成公钥和私钥对应的文件(默认路径:./pub.key,./priv.key)`, + Run: func(cmd *cobra.Command, args []string) { + pub, pri, _, _ := logic.GenerateKeyPair() + err := os.WriteFile("priv.key", pri, 0666) + if err != nil { + fmt.Printf("generate private key has some err %v\n", err) + os.Exit(1) + } + err = os.WriteFile("pub.key", pub, 0666) + if err != nil { + fmt.Printf("generate public key has some err %v\n", err) + os.Exit(1) + } + + fmt.Println("generate private key in ./priv.key") + fmt.Println("generate public key in ./pub.key") + }, +} + +// 签名 +var signCmd = &cobra.Command{ + Use: "sign [message]", + Short: "将传入的message信息进行签名", + Long: `使用私钥将传入的message信息进行签名,并生成base64编码后的签名信息`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + message := args[0] + privateKeyBytes, err := os.ReadFile(privateKeyPath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + messageHash := logic.Hash([]byte(message)) + signatureBytes, err := logic.SignSignature(messageHash, privateKeyBytes) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + signature := base64.StdEncoding.EncodeToString(signatureBytes) + + fmt.Printf("Message: %s\n", message) + fmt.Printf("Signature: %s\n", signature) + }, +} + +// 生成weid信息 +var genWeIdCmd = &cobra.Command{ + Use: "gendid", + Short: "通过读取公钥和私钥信息,创建did", + Long: "公钥用于生成did,私钥用于创建上链(did链)的签名信息", + Run: func(cmd *cobra.Command, args []string) { + privateKeyBytes, err := os.ReadFile(privateKeyPath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + publicKeyBytes, err := os.ReadFile(publicKeyPath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + weid, err := logic.CreateWeId(didServiceIp, didServicePort, publicKeyBytes, privateKeyBytes) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + fmt.Printf("generate weid success: %s\n", weid) + }, +} + +func init() { + rootCmd.AddCommand(keyCmd) + signCmd.PersistentFlags().StringVarP(&privateKeyPath, "private key path", "p", "", "用户私钥文件的路径") + rootCmd.AddCommand(signCmd) + genWeIdCmd.Flags().StringVarP(&publicKeyPath, "public key path", "p", "", "用户公钥文件地址") + genWeIdCmd.Flags().StringVarP(&privateKeyPath, "private key path", "s", "", "用户私钥文件地址") + genWeIdCmd.Flags().StringVarP(&didServiceIp, "did service ip", "i", "", "did服务ip地址") + genWeIdCmd.Flags().StringVarP(&didServicePort, "did service port", "t", "", "did服务port地址") + rootCmd.AddCommand(genWeIdCmd) +} + +func main() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/weidentity-task1/src/sign-in-with-did-web/web1/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web1/.DS_Store new file mode 100644 index 00000000..76b2d8ed Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web1/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web1/src/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web1/src/.DS_Store new file mode 100644 index 00000000..94e6b2bd Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web1/src/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/.DS_Store new file mode 100644 index 00000000..6d4b6639 Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/images/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/images/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web1/src/assets/images/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web2/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web2/.DS_Store new file mode 100644 index 00000000..76b2d8ed Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web2/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web2/src/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web2/src/.DS_Store new file mode 100644 index 00000000..94e6b2bd Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web2/src/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/.DS_Store new file mode 100644 index 00000000..6d4b6639 Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/.DS_Store differ diff --git a/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/images/.DS_Store b/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/images/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/weidentity-task1/src/sign-in-with-did-web/web2/src/assets/images/.DS_Store differ diff --git "a/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.assets/image-20230530105353141.png" "b/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.assets/image-20230530105353141.png" new file mode 100644 index 00000000..5a105bc7 Binary files /dev/null and "b/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.assets/image-20230530105353141.png" differ diff --git "a/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.md" "b/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.md" new file mode 100644 index 00000000..84f95d95 --- /dev/null +++ "b/\345\274\200\345\217\221\345\237\272\344\272\216DID\347\232\204\346\225\260\346\215\256\346\216\210\346\235\203\345\205\261\344\272\253\346\241\210\344\276\213.md" @@ -0,0 +1,299 @@ +# **Task 20** + +#### **任务** + +开发基于DID的数据授权共享案例(定义具体且通用的数据结构,在数据的拥有者授权下某些应用方可以更改或查询拥有者的部分数据) + +#### 构想案例 + +构想设计一个人才链系统,该人才链系统里面人才可以和企业去签约信息,人才可以授权企业去修改对应签约信息,同时人才也可以通过获取和企业认证获取真实项目经验的凭证。(目前只涉及到了人才可以授权企业去修改对应签约信息) + +#### **设计思路** + +1.数据结构定义:需要定义一个通用的数据结构,包含拥有者的身份信息和关键数据字段。这些数据字段用来标识所对应的用户数据的授权情况。 + +2.DID标识符生成:每个参与者(人才或企业)都需要注册一个 WeIdentity DID,并在区块链上进行身份认证。 + +3.授权管理与验证:拥有者可以通过智能合约实现对自己的数据进行授权管理,即授权特定的应用方查询或修改自己的部分数据。同时,在数据被访问时,需要进行授权验证,以确保只有被授权的应用方才能访问数据。 + +4.数据管理:核心数据放入后端程序中,链上只记录每个数据授权对象的授权状态。 + +5.使用 Credential 来授权数据访问:人才可以授权企业对其签约信息进行修改,并可以通过获取和企业认证获得真实项目经验的凭证。为此,人才可以使用 Credential 模块创建一个包含签约信息和项目经验的凭证,并将其授权给指定的企业进行访问。这样,企业就可以在合法授权的前提下修改人才的签约信息,并获取到人才的真实项目经验 + +#### **流程图** + +![image-20230530105353141](开发基于DID的数据授权共享案例.assets/image-20230530105353141.png) + +#### 合约功能设计 + +合约应该让用户可以管理自己的个人信息,并授权其他用户访问这些信息。同时,颁发机构可以通过该合约来颁发凭证。 + +1. 颁发机构可以给每个用户颁发对应的凭证。 +2. 用户可以授权其他用户访问自己的信息,并设置不同的权限级别。 +3. 用户可以撤销对其他用户信息的访问授权。 +4. 凭证的拥有者可以更新其凭证的数据。 +5. 允许任何用户查看特定凭证的详细信息。 +6. 检查凭证是否有效。 + +#### **合约代码** + +```solidity +pragma solidity ^0.8.0; + +contract Credential { + address private issuer; // 颁发机构地址 + + uint256 totalCredentialId; //凭证总发行量 + + struct CredentialData { + uint256 credentialId; // 凭证ID + address wid; // 凭证拥有者的地址(wid) + string dataHash; // 凭证数据的hash + } + + //用户数据,0无权限,1仅查看,2可修改 用户地址=》被授权用户地址=》权限 + mapping(address => mapping(address => uint)) public idCard; // 用户身份证授权 + mapping(address => mapping(address => uint)) public phoneNumber; // 用户电话号码授权 + mapping(address => mapping(address => uint)) public email; // 用户邮箱授权 + mapping(address => mapping(address => uint)) public education; // 用户学历信息授权 + mapping(address => mapping(uint => uint)) public learningExperience; // 用户学习项目授权 + mapping(address => mapping(uint => uint)) public projectExperience; // 用户项目经历授权 + mapping(address => mapping(uint => uint)) public enterpriseContract; // 用户企业合同授权 + + mapping(address => CredentialData) public credentials; // 存储每个用户的CredentialData + mapping(address => mapping(uint => bool)) public isCredentialOwner; // 是否是数据拥有者 + + event CredentialIssued( + uint256 credentialId, + address indexed owner, + address indexed issuer + ); + event CredentialUpdated(uint256 credentialId, string newData); + event CredentialApprovalChanged(uint256 credentialId, bool isApproved); + + constructor() { + issuer = msg.sender; + } + + modifier onlyIssuer() { + require( + msg.sender == issuer, + "Only the authority can call this function" + ); + _; + } + + modifier onlyCredentialOwner(address _owner, uint _credentialId) { + require( + isCredentialOwner[_owner][_credentialId], + "Only credential owner can call this function" + ); + _; + } + + // 允许颁发机构更新颁发机构的地址 + function setIssuer(address _issuer) external onlyIssuer { + issuer = _issuer; + } + + // 颁发机构可以给每个用户颁发对应的凭证 + function issueCredential( + address user, + string memory dataHash + ) external onlyIssuer { + CredentialData storage newCredential = credentials[user]; + newCredential.credentialId = totalCredentialId; + newCredential.wid = user; + newCredential.dataHash = dataHash; + + emit CredentialIssued(totalCredentialId, user, issuer); + totalCredentialId++; + } + + // 对用户数据进行查看和操作的时候,先验证hash是否一致 + function verifyHash( + address user, + string memory dataHash + ) internal view returns (bool) { + require(credentials[user].credentialId != 0, "user has no credentials"); + return + keccak256(abi.encodePacked(credentials[user].dataHash)) == + keccak256(abi.encodePacked(dataHash)); + } + + /** + * @dev 允许用户授权其他用户访问自己的信息 + * @param user 被授权用户 + * @param credentialId 用户IDcredentialId + * @param accessLevel 授权状态 + * @param infoIndex 信息索引 + * @param learningExperienceId 学习经历ID + * @param projectExperienceId 项目经历ID + * @param enterpriseContractId 企业合同ID + */ + function authorizeAccess( + address user, + uint256 credentialId, + uint[] memory accessLevel, + uint[] memory infoIndex, + uint learningExperienceId, + uint projectExperienceId, + uint enterpriseContractId + ) external onlyCredentialOwner(msg.sender, credentialId){ + validateCredential(user, credentialId); + require( + accessLevel.length == infoIndex.length, + "array length mismatch" + ); + + for (uint i = 0; i < infoIndex.length; i++) { + require( + infoIndex[i] >= 1 && infoIndex[i] <= 7, + "invalid information index" + ); + + if (infoIndex[i] == 1) { + idCard[msg.sender][user] = accessLevel[i]; + } else if (infoIndex[i] == 2) { + phoneNumber[msg.sender][user] = accessLevel[i]; + } else if (infoIndex[i] == 3) { + email[msg.sender][user] = accessLevel[i]; + } else if (infoIndex[i] == 4) { + education[msg.sender][user] = accessLevel[i]; + } else if (infoIndex[i] == 5) { + learningExperience[msg.sender][ + learningExperienceId + ] = accessLevel[i]; + } else if (infoIndex[i] == 6) { + projectExperience[msg.sender][ + projectExperienceId + ] = accessLevel[i]; + } else if (infoIndex[i] == 7) { + enterpriseContract[msg.sender][ + enterpriseContractId + ] = accessLevel[i]; + } else { + revert("invalid information index"); + } + } + } + + /** + * @dev 检查用户是否有权限访问信息 + * @param user 被查看信息的用户 + * @param infoIndex 信息索引 + * @param learningExperienceId 学习经历ID + * @param projectExperienceId 项目经历ID + * @param enterpriseContractId 企业合同ID + */ + function checkAccess( + address user, + uint infoIndex, + uint learningExperienceId, + uint projectExperienceId, + uint enterpriseContractId + ) public view returns (bool) { + if (infoIndex == 1) { + return idCard[user][msg.sender] > 0; + } else if (infoIndex == 2) { + return phoneNumber[user][msg.sender] > 0; + } else if (infoIndex == 3) { + return email[user][msg.sender] > 0; + } else if (infoIndex == 4) { + return education[user][msg.sender] > 0; + } else if (infoIndex == 5) { + return learningExperience[user][learningExperienceId] > 0; + } else if (infoIndex == 6) { + return projectExperience[user][projectExperienceId] > 0; + } else if (infoIndex == 7) { + return enterpriseContract[user][enterpriseContractId] > 0; + } else { + revert("invalid information index"); + } + + return false; + } + + /** + * @dev 撤销用户对其他用户信息访问授权 + * @param revokedUser 被撤销访问权限的用户 + * @param credentialId 用户credentialId + * @param infoIndex 信息索引 + * @param learningExperienceId 学习经历ID + * @param projectExperienceId 项目经历ID + * @param enterpriseContractId 企业合同ID + */ + function revokeAccess( + address revokedUser, + uint256 credentialId, + uint infoIndex, + uint learningExperienceId, + uint projectExperienceId, + uint enterpriseContractId + ) external onlyCredentialOwner(msg.sender, credentialId){ + + if (infoIndex == 1) { + idCard[revokedUser][msg.sender] = 0; + } else if (infoIndex == 2) { + phoneNumber[revokedUser][msg.sender] = 0; + } else if (infoIndex == 3) { + email[revokedUser][msg.sender] = 0; + } else if (infoIndex == 4) { + education[revokedUser][msg.sender] = 0; + } else if (infoIndex == 5) { + learningExperience[revokedUser][learningExperienceId] = 0; + } else if (infoIndex == 6) { + projectExperience[revokedUser][projectExperienceId] = 0; + } else if (infoIndex == 7) { + enterpriseContract[revokedUser][enterpriseContractId] = 0; + } else { + revert("invalid information index"); + } + } + + //允许凭证的拥有者更新其凭证的数据 + function updateCredentialData( + uint256 credentialId, + string memory newData + ) external onlyCredentialOwner(msg.sender, credentialId){ + validateCredential(msg.sender, credentialId); + require(verifyHash(msg.sender, newData), "data inconsistency"); + + credentials[msg.sender].dataHash = newData; + emit CredentialUpdated(credentialId, newData); + } + + //允许任何用户查看特定凭证的详细信息 + function getCredentialInfo( + address user, + uint256 credentialId + ) external view returns (uint256, address, string memory) { + validateCredential(user, credentialId); + CredentialData storage credential = credentials[user]; + return (credential.credentialId, credential.wid, credential.dataHash); + } + + // 检查凭证是否有效 + function validateCredential( + address user, + uint256 credentialId + ) internal view { + require(credentials[user].credentialId != 0, "user has no credentials"); + require( + credentialId < credentials[user].credentialId, + "invalid credential id" + ); + } +} + + +``` + +#### 后端操作 + +1. 颁发机构调用 `issueCredential` 函数来颁发用户的凭证。 +2. 用户调用 `authorizeAccess` 函数来授权其他用户访问自己的信息,并设置不同的权限级别。 +3. 用户调用 `revokeAccess` 函数来撤销对其他用户信息的访问授权。 +4. 凭证的拥有者调用 `updateCredentialData` 函数来更新其凭证的数据。 +5. 任何用户可以调用 `getCredentialInfo` 函数来查看特定凭证的详细信息。 +6. 在进行操作之前,应该先调用 `validateCredential` 函数来检查凭证是否有效。