├── .idea
├── did-sdk-java.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── CHANGELOG.md
├── LICENSE
├── README-ko.md
├── README.md
├── build.gradle
├── build
├── libs
│ └── did-sdk-java-0.8.3.jar
└── tmp
│ └── jar
│ └── MANIFEST.MF
├── did-sdk-java.iml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lib
├── build.gradle
├── build
│ └── libs
│ │ └── icon-did-0.8.6.jar
└── src
│ ├── main
│ └── java
│ │ └── foundation
│ │ └── icon
│ │ └── did
│ │ ├── Credential.java
│ │ ├── DidService.java
│ │ ├── Presentation.java
│ │ ├── core
│ │ ├── Algorithm.java
│ │ ├── AlgorithmProvider.java
│ │ ├── DidKeyHolder.java
│ │ ├── ES256Algorithm.java
│ │ ├── ES256KAlgorithm.java
│ │ ├── KeyProvider.java
│ │ ├── Keystore.java
│ │ ├── KeystoreFile.java
│ │ ├── NoneAlgorithm.java
│ │ ├── PropertyName.java
│ │ └── RS256Algorithm.java
│ │ ├── document
│ │ ├── AuthenticationProperty.java
│ │ ├── Converters.java
│ │ ├── Document.java
│ │ ├── EncodeType.java
│ │ ├── Encoder.java
│ │ └── PublicKeyProperty.java
│ │ ├── exceptions
│ │ ├── AlgorithmException.java
│ │ ├── JwtException.java
│ │ ├── KeyPairException.java
│ │ ├── KeystoreException.java
│ │ ├── ResolveException.java
│ │ └── TransactionException.java
│ │ ├── jwt
│ │ ├── ConvertJwt.java
│ │ ├── Header.java
│ │ ├── IssuerDid.java
│ │ ├── Jwt.java
│ │ └── Payload.java
│ │ ├── protocol
│ │ └── ClaimRequest.java
│ │ └── score
│ │ ├── DidScore.java
│ │ └── ScoreParameter.java
│ └── test
│ ├── java
│ └── foundation
│ │ └── icon
│ │ └── did
│ │ ├── ClaimRequestTest.java
│ │ ├── CredentialTest.java
│ │ ├── DIDBuildJwtTest.java
│ │ ├── DidJwtServiceTest.java
│ │ ├── IconServiceFactory.java
│ │ ├── IssuerDidTest.java
│ │ ├── JJwtTest.java
│ │ ├── PemUtilsTest.java
│ │ ├── PresentationTest.java
│ │ ├── RepeatedTest.java
│ │ ├── TempFileProvider.java
│ │ ├── TestKeys.java
│ │ └── core
│ │ ├── AlgorithmProvider.java
│ │ ├── AlgorithmTest.java
│ │ ├── KeyProviderTest.java
│ │ └── KeystoreTest.java
│ └── resources
│ ├── ec256-key-pair.pem
│ ├── ec256-key-private.pem
│ ├── ec256-key-public-invalid.pem
│ ├── ec256-key-public.pem
│ ├── ec384-key-pair.pem
│ ├── ec384-key-private.pem
│ ├── ec384-key-public-invalid.pem
│ ├── ec384-key-public.pem
│ ├── ec512-key-pair.pem
│ ├── ec512-key-private.pem
│ ├── ec512-key-public-invalid.pem
│ ├── ec512-key-public.pem
│ ├── rsa-private.pem
│ ├── rsa-public.pem
│ └── rsa-public_invalid.pem
├── sample
├── README.md
├── build.gradle
├── build
│ ├── classes
│ │ └── java
│ │ │ └── main
│ │ │ └── foundation
│ │ │ └── icon
│ │ │ └── did
│ │ │ ├── CredentialSample.class
│ │ │ ├── DidManageSample.class
│ │ │ ├── KeyPoviderSample.class
│ │ │ ├── PresentationSample.class
│ │ │ ├── api
│ │ │ ├── ApiResponse.class
│ │ │ ├── AuthResponse.class
│ │ │ ├── ClaimIssueApi$Api.class
│ │ │ ├── ClaimIssueApi.class
│ │ │ └── CredentialResponse.class
│ │ │ ├── config
│ │ │ ├── DevConfig.class
│ │ │ ├── LocalConfig.class
│ │ │ ├── SampleConfig.class
│ │ │ └── SampleKeys.class
│ │ │ ├── exception
│ │ │ └── SampleException.class
│ │ │ └── util
│ │ │ └── FileUtils.class
│ ├── libs
│ │ └── sample-0.8.3.jar
│ └── tmp
│ │ └── jar
│ │ └── MANIFEST.MF
└── src
│ └── main
│ └── java
│ └── foundation
│ └── icon
│ └── did
│ ├── CredentialSample.java
│ ├── DidManageSample.java
│ ├── KeyPoviderSample.java
│ ├── PresentationSample.java
│ ├── api
│ ├── ApiResponse.java
│ ├── AuthResponse.java
│ ├── ClaimIssueApi.java
│ └── CredentialResponse.java
│ ├── config
│ ├── DevConfig.java
│ ├── LocalConfig.java
│ ├── SampleConfig.java
│ └── SampleKeys.java
│ ├── exception
│ └── SampleException.java
│ └── util
│ └── FileUtils.java
└── settings.gradle
/.idea/did-sdk-java.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Class structureJava
13 |
14 |
15 | Java
16 |
17 |
18 | Probable bugsJava
19 |
20 |
21 |
22 |
23 | Android
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | 1561605529461
87 |
88 |
89 | 1561605529461
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | 1.8
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 0.8.3 (2019-5-15)
4 | - Remove CryptoUtils class
5 | - Move EncodeType class to upper level
6 |
7 | ## 0.8.2 (2019-5-14)
8 | - Change to use encoded token string instead of signature in Jwt class
9 |
10 | ## 0.8.1 (2019-5-3)
11 | - Move generateKeyPair method to Algorithm object
12 |
13 | ## 0.8.0 (2019-5-2)
14 | - Remove korean text in code
15 | - rename package : com.nomadconnection.icondid => foundation.icon.did
16 | - rename files
17 | old : DidOperationFactory, DidClaim, IClaim, DidRegistryScore
18 | new : ScoreParameter, IssuerDid, ConvertJwt, DidScore
19 | - Add DidKeyHolder class
20 | - Move sign method of ConvertJwt to DidKeyHolder
21 |
22 | ## 0.7.3 (2019-4-23)
23 | - DID Document create method 수정 : JWT format 에서 json object format 으로 변경
24 | - deprecated method 제거
25 |
26 | ## 0.7.2 (2019-3-26)
27 | - DID Document 에서 hash property 제거 (createTxHash, updateTxHash)
28 | - JWT Header 에서 type property 제거
29 | - credential, presentation 에 nonce property 추가
30 | - Credential, Presentation 의 type 에 default value 추가 ("credential", "presentation")
31 | - ClaimResponse class 제거
32 | - ClaimRequest 의 requestClaims method param type 변경 (List -> Map)
33 | - ClaimRequest 에 responseId 추가
34 | - ClaimRequest 에 unsigned jwt 추가
35 | - Document 의 publicKey type property 수정 (String -> List)
36 | - DID Document 의 addKey method 수정
37 | - Presentation 의 claims property 이름 변경 (claims -> credential)
38 |
39 | ## 0.6.1 (2019-3-21)
40 | - ClaimRequest 추가 : Issuer 에게 Credential 요청, Owner 에게 Presentation 요청
41 | - PublicKey 의 string encode type 은 BASE64 만 지원 (Hex 인 경우, score 에서 revert)
42 | - Credential 과 Presentation 의 payload 수정
43 | - type 이 list 타입으로 변경
44 | - type 변경으로 credential 의 claim 추가 방법 변경 (기존 Credential.setClaim 메소드 변경)
45 | - PublicKey 의 type 이름 변경 : Secp256k1VerificationKey
46 | - DID Document 의 created, updated, revoked 가 timestamp 에서 block height 으로 변경
47 |
48 | ## 0.5.3 (2019-3-7)
49 | - Change property in Authentication
50 | - Add missing update properties
51 |
52 | ## 0.5.2 (2019-2-27)
53 | - icon-sdk-java version 업데이트
54 | - ES256KAlgorithm sign/verify 할 때, DER format 인코딩/디코딩 제거
55 | - DidOperationFactory class 추가 (DID CRUD 요청 생성)
56 |
57 | ## 0.5.1 (2019-1-30)
58 | - public key revoke 체크 method 추가
59 |
60 | ## 0.5.0 (2019-1-29)
61 | - ES256K Algorithm 추가
62 | - 각 Algotihm 별 클래스 추가 (ES256Algorithm, RS256Algorithm)
63 | - Algorithm 클래스 AlgorithmProvider 로 변경
64 | - ecdsa_verify 추가한 score 연동 테스트
65 |
66 | ## 0.4.0 (2019-1-24)
67 | - `icon.did` 패키지 `core` 패키지로 변경
68 | - PublicKeyProperty class 에서 사용하던 KeyProvider 제거
69 | - KeyProvider 에 private key 추가
70 | - Algorithm 클래스 추가
71 | - JwtUtils 클래스 제거
72 | - Keystore 클래스 추가 (private key 와 did 저장)
73 |
74 | ## 0.3.0 (2019-1-22)
75 |
76 | - JWT 로 score 호출 메소드 추가
77 | - VerifyResult class 추가
78 | - Jwt.verify 할 때, expiration time 확인 추가
79 | - Jwt, JwtFactory `com.nomadconnection.icondid.jwt` 패키지 이동
80 |
81 | ## 0.2.0 (2019-1-15)
82 |
83 | - DidJwt 에서 Jwt 로 변경
84 | - DidKeyPair 에서 KeyProvider 로 변경
85 | - KeyProvider 에 PrivateKey 제거
86 | - 패키지 구조 변경
87 | - document 패키지 추가
88 |
89 |
90 | ## 0.1.1 (2018-12-24)
91 |
92 | - public key `add`, `revoke` 추가 [5a44e36c](https://gitlab.com/did-vault/did-sdk-java/commit/5a44e36cad57b5319ba4ef3f3ff1ad65d64c0de9)
93 | - New bicon-score : cxf847b8a788e2c978b57a8905fcdb7ed359b013a2
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 |
5 | allprojects {
6 | group GROUP
7 | version VERSION_NAME
8 | }
9 |
10 | subprojects {
11 | repositories {
12 | mavenCentral()
13 | }
14 | }
15 |
16 | task stage(dependsOn: ['clean', 'build'])
--------------------------------------------------------------------------------
/build/libs/did-sdk-java-0.8.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/build/libs/did-sdk-java-0.8.3.jar
--------------------------------------------------------------------------------
/build/tmp/jar/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 |
3 |
--------------------------------------------------------------------------------
/did-sdk-java.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2018 ICON Foundation.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | GROUP=foundation.icon
18 | VERSION_NAME=0.8.6
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Dec 20 15:21:30 KST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/lib/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 |
5 | sourceCompatibility = 1.8
6 |
7 | repositories {
8 | mavenCentral()
9 | }
10 |
11 | ext {
12 | bouncycastleVersion = '1.60'
13 | iconSdkVersion = '0.9.11'
14 | gsonVersion = '2.8.0'
15 | okhttpVersion = '3.11.0'
16 | junitVersion = '5.4.0-RC2'
17 | logbackVersion = '1.2.3'
18 | javaJwtVersion = '3.5.0'
19 | }
20 |
21 | dependencies {
22 | implementation "com.google.code.gson:gson:$gsonVersion"
23 | implementation "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
24 | implementation "foundation.icon:icon-sdk:$iconSdkVersion"
25 | implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
26 |
27 | testImplementation "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
28 | testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
29 |
30 | // test jjwt
31 | testImplementation 'io.jsonwebtoken:jjwt-api:0.10.5'
32 | testRuntimeOnly 'io.jsonwebtoken:jjwt-impl:0.10.5'
33 | testRuntimeOnly('io.jsonwebtoken:jjwt-orgjson:0.10.5') {
34 | exclude group: 'org.json', module: 'json' //provided by Android natively
35 | }
36 | testImplementation 'io.jsonwebtoken:jjwt-jackson:0.10.5'
37 | }
38 |
39 | jar {
40 | baseName = 'icon-did'
41 | }
--------------------------------------------------------------------------------
/lib/build/libs/icon-did-0.8.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/lib/build/libs/icon-did-0.8.6.jar
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/Credential.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.DidKeyHolder;
5 | import foundation.icon.did.jwt.ConvertJwt;
6 | import foundation.icon.did.jwt.IssuerDid;
7 | import foundation.icon.did.jwt.Jwt;
8 | import foundation.icon.did.jwt.Payload;
9 |
10 | import java.util.*;
11 |
12 | /**
13 | * This class to create a verifiable credential, which can be used to express information that a credential represents.
14 | * (for example, a city government, national agency, or identification number)
15 | *
16 | * For credential to be verifiable, proof mechanism use Json Web Token.
17 | * You can generate a complete JWT (with Signature) by calling {@linkplain DidKeyHolder#sign(Jwt)}.
18 | *
19 | * A credential is a set of one or more claims.
20 | * It might also include metadata to describe properties of the credential, such as the issuer,
21 | * the expiry time, the issued time, an algorithm for verification, and so on.
22 | *
23 | * These claims and metadata must be signed by the issuer.
24 | * After that, you can generate {@linkplain Presentation presentation}.
25 | */
26 | public class Credential implements ConvertJwt {
27 |
28 | private int expDuration = 24 * 60 * 60; // seconds
29 | public static final String DEFAULT_TYPE = "CREDENTIAL";
30 |
31 | private IssuerDid issuerDid;
32 | private String targetDid;
33 | private Map claim;
34 | private String nonce;
35 | private String jti;
36 | private String version;
37 |
38 | public Credential(IssuerDid issuerDid) {
39 | this.issuerDid = issuerDid;
40 | claim = new HashMap<>();
41 | }
42 |
43 | /**
44 | * Set the did of the owner that holds the credential.
45 | *
46 | * @param did : the did
47 | */
48 | public void setTargetDid(String did) {
49 | this.targetDid = did;
50 | }
51 |
52 | /**
53 | * Add the information that express the owner's credential.
54 | *
55 | * @param type : the type of claim (email, phone, gender)
56 | * @param value : the value of claim (abc@abc.com, 01012345678, M)
57 | */
58 | public void addClaim(String type, String value) {
59 | claim.put(type, value);
60 | }
61 |
62 | /**
63 | * Set the information that express the owner's credentials.
64 | *
65 | * @param claim : the map of claim {"Email":"aaa@icon.foundation"}
66 | */
67 | public void setClaim(Map claim) {
68 | this.claim = claim;
69 | }
70 |
71 | /**
72 | * Set a unique identifier for the credential. (Optional)
73 | *
74 | * @param nonce : the string object
75 | */
76 | public void setNonce(String nonce) {
77 | this.nonce = nonce;
78 | }
79 |
80 | /**
81 | * Set a unique identifier for the JWT.
82 | *
83 | * @param jti : the string object
84 | */
85 | public void setJti(String jti) {
86 | this.jti = jti;
87 | }
88 |
89 | public void setVersion(String version) { this.version = version; }
90 |
91 | public String getTargetDid() {
92 | return targetDid;
93 | }
94 |
95 | public IssuerDid getIssuerDid() {
96 | return issuerDid;
97 | }
98 |
99 | public Map getClaim() {
100 | return claim;
101 | }
102 |
103 | public List getTypes() {
104 | ArrayList types = new ArrayList<>(claim.keySet());
105 | types.add(0, DEFAULT_TYPE);
106 | return types;
107 | }
108 |
109 | public String getDid() {
110 | return issuerDid.getDid();
111 | }
112 |
113 | public String getKeyId() {
114 | return issuerDid.getKeyId();
115 | }
116 |
117 | public String getAlgorithm() {
118 | return issuerDid.getAlgorithm();
119 | }
120 |
121 | public String getNonce() {
122 | return nonce;
123 | }
124 |
125 | public String getJti() {
126 | return jti;
127 | }
128 |
129 | public String getVersion() { return version; }
130 |
131 | @Override
132 | public int getDuration() {
133 | return expDuration;
134 | }
135 |
136 | @Override
137 | public Jwt buildJwt(Date issued, Date expiration) {
138 | String kid = issuerDid.getDid() + "#" + issuerDid.getKeyId();
139 | return new Jwt.Builder()
140 | .alg(issuerDid.getAlgorithm())
141 | .kid(kid)
142 | .version(version)
143 | .sub(targetDid)
144 | .iss(issuerDid.getDid())
145 | .iat(issued)
146 | .exp(expiration)
147 | .type(getTypes())
148 | .claim(claim)
149 | .nonce(nonce)
150 | .jti(jti)
151 | .build();
152 | }
153 |
154 | /**
155 | * Returns the credential object representation of the String argument.
156 | *
157 | * @param encodedJwt the String returned by calling {@linkplain DidKeyHolder#sign(Jwt)}
158 | * @return the credential object
159 | */
160 | public static Credential valueOf(String encodedJwt) {
161 | return valueOf(Jwt.decode(encodedJwt));
162 | }
163 |
164 |
165 | /**
166 | * Returns the credential object representation of the Jwt argument.
167 | *
168 | * @param jwt the JWT with properties of the Credential object
169 | * @return the credential object
170 | * @see Credential#buildJwt(Date, Date)
171 | */
172 | public static Credential valueOf(Jwt jwt) {
173 | Payload payload = jwt.getPayload();
174 | IssuerDid issuerDid = IssuerDid.valueOf(jwt);
175 | return new Builder(issuerDid)
176 | .targetDid(payload.getSub())
177 | .claim(payload.getClaim())
178 | .nonce(jwt.getPayload().getNonce())
179 | .build();
180 | }
181 |
182 | public static final class Builder {
183 | private IssuerDid.Builder issuerBuilder;
184 | private IssuerDid issuerDid;
185 |
186 | private String targetDid;
187 | private Map claim;
188 | private String nonce;
189 |
190 | public Builder() {
191 | this.issuerBuilder = new IssuerDid.Builder();
192 | }
193 |
194 | public Builder(IssuerDid issuerDid) {
195 | this();
196 | this.issuerDid = issuerDid;
197 | }
198 |
199 | public Builder didKeyHolder(DidKeyHolder keyHolder) {
200 | this.issuerBuilder.algorithm(keyHolder.getType().getName())
201 | .keyId(keyHolder.getKeyId())
202 | .did(keyHolder.getDid());
203 | return this;
204 | }
205 |
206 | public Builder algorithm(String algorithm) {
207 | this.issuerBuilder.algorithm(algorithm);
208 | return this;
209 | }
210 |
211 | public Builder keyId(String algorithm) {
212 | this.issuerBuilder.keyId(algorithm);
213 | return this;
214 | }
215 |
216 | public Builder did(String did) {
217 | this.issuerBuilder.did(did);
218 | return this;
219 | }
220 |
221 | public Builder targetDid(String val) {
222 | targetDid = val;
223 | return this;
224 | }
225 |
226 | public Builder nonce(String nonce) {
227 | this.nonce = nonce;
228 | return this;
229 | }
230 |
231 | public Builder claim(Map val) {
232 | claim = val;
233 | return this;
234 | }
235 |
236 | public Credential build() {
237 | if (issuerDid == null) {
238 | issuerDid = issuerBuilder.build();
239 | }
240 | IssuerDid.Builder.checkArgument(issuerDid, "issuerDid not found");
241 |
242 | Credential credential = new Credential(issuerDid);
243 | credential.targetDid = this.targetDid;
244 | credential.nonce = this.nonce;
245 | if (this.claim != null) credential.claim = this.claim;
246 | return credential;
247 | }
248 | }
249 |
250 | @Override
251 | public String toString() {
252 | return "Credential{" +
253 | "issuerDid=" + issuerDid +
254 | ", targetDid='" + targetDid + '\'' +
255 | ", claim=" + claim +
256 | ", nonce='" + nonce + '\'' +
257 | ", jti='" + jti + '\'' +
258 | '}';
259 | }
260 | }
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/Presentation.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.DidKeyHolder;
5 | import foundation.icon.did.jwt.ConvertJwt;
6 | import foundation.icon.did.jwt.IssuerDid;
7 | import foundation.icon.did.jwt.Jwt;
8 | import foundation.icon.did.jwt.Payload;
9 |
10 | import java.util.ArrayList;
11 | import java.util.Date;
12 | import java.util.List;
13 |
14 | /**
15 | * This class use to create a verifiable presentation.
16 | *
17 | * A verifiable presentation expresses data from one or more credentials, and is packaged in
18 | * such a way that the authorship of the data is verifiable.
19 | *
20 | * This object must be signed by the owner of the credential.
21 | * And you can send a specific verifier.
22 | *
23 | * The verifier can verify the authenticity of the presentation and credentials,
24 | * and also verify that the owner possesses the credential
25 | */
26 | public class Presentation implements ConvertJwt {
27 |
28 | private final static int EXP_DURATION = 5 * 60; // seconds
29 | public static final String DEFAULT_TYPE = "PRESENTATION";
30 |
31 | private IssuerDid issuerDid;
32 | private List types;
33 | private List credentials;
34 | private String nonce;
35 | private String jti;
36 | private String version;
37 |
38 | public Presentation(IssuerDid issuerDid) {
39 | this.issuerDid = issuerDid;
40 | this.credentials = new ArrayList<>();
41 | this.types = new ArrayList<>();
42 | }
43 |
44 | /**
45 | * Add the credential
46 | *
47 | * @param claim the credential signed by issuer, the string is the encoded jwt
48 | * {@linkplain DidKeyHolder#sign(Jwt)}
49 | */
50 | public void addCredential(String claim) {
51 | credentials.add(claim);
52 | Credential credential = Credential.valueOf(claim);
53 | List credentialTypes = credential.getTypes();
54 | credentialTypes.remove(Credential.DEFAULT_TYPE);
55 | this.types.addAll(credentialTypes);
56 | }
57 |
58 | /**
59 | * Set the list of credential
60 | *
61 | * @param credentials the list of credential
62 | */
63 | public void setCredentials(List credentials) {
64 | this.types.clear();
65 | for (String c : credentials) {
66 | addCredential(c);
67 | }
68 | }
69 |
70 | /**
71 | * Set a unique identifier for the presentation (Optional)
72 | *
73 | * @param nonce : the string object
74 | */
75 | public void setNonce(String nonce) {
76 | this.nonce = nonce;
77 | }
78 |
79 | /**
80 | * Set a unique identifier for the JWT
81 | *
82 | * @param jti : the string object
83 | */
84 | public void setJti(String jti) {
85 | this.jti = jti;
86 | }
87 |
88 |
89 | public void setVersion(String version) { this.version = version; }
90 |
91 | public String getDid() {
92 | return issuerDid.getDid();
93 | }
94 |
95 | public String getKeyId() {
96 | return issuerDid.getKeyId();
97 | }
98 |
99 | public String getAlgorithm() {
100 | return issuerDid.getAlgorithm();
101 | }
102 |
103 | public List getTypes() {
104 | List result = new ArrayList<>(this.types);
105 | result.add(0, DEFAULT_TYPE);
106 | return result;
107 | }
108 |
109 | public String getNonce() {
110 | return nonce;
111 | }
112 |
113 | public String getJti() {
114 | return jti;
115 | }
116 |
117 | public String getVersion() {return version; }
118 |
119 | @Override
120 | public int getDuration() {
121 | return EXP_DURATION;
122 | }
123 |
124 | @Override
125 | public Jwt buildJwt(Date issued, Date expiration) {
126 | String kid = issuerDid.getDid() + "#" + issuerDid.getKeyId();
127 | return new Jwt.Builder()
128 | .alg(issuerDid.getAlgorithm())
129 | .kid(kid)
130 | .iss(issuerDid.getDid())
131 | .iat(issued)
132 | .exp(expiration)
133 | .type(getTypes())
134 | .credential(credentials)
135 | .nonce(nonce)
136 | .jti(jti)
137 | .version(version)
138 | .build();
139 | }
140 |
141 | /**
142 | * Returns the presentation object representation of the String argument.
143 | *
144 | * @param encodedJwt the String returned by calling {@linkplain DidKeyHolder#sign(Jwt)}
145 | * @return the presentation object
146 | */
147 | public static Presentation valueOf(String encodedJwt) {
148 | return valueOf(Jwt.decode(encodedJwt));
149 | }
150 |
151 | /**
152 | * Returns the presentation object representation of the Jwt argument.
153 | *
154 | * @param jwt the JWT with properties of the Presentation object
155 | * @return the presentation object
156 | * @see Presentation#buildJwt(Date, Date)
157 | */
158 | public static Presentation valueOf(Jwt jwt) {
159 | Payload payload = jwt.getPayload();
160 | IssuerDid issuerDid = IssuerDid.valueOf(jwt);
161 | return new Builder(issuerDid)
162 | .credentials(payload.getCredential())
163 | .nonce(payload.getNonce())
164 | .build();
165 | }
166 |
167 | public static final class Builder {
168 | private IssuerDid.Builder issuerBuilder;
169 | private IssuerDid issuerDid;
170 | private List credentials;
171 | private String nonce;
172 | private String version;
173 |
174 | public Builder() {
175 | this.issuerBuilder = new IssuerDid.Builder();
176 | }
177 |
178 | public Builder(IssuerDid issuerDid) {
179 | this();
180 | this.issuerDid = issuerDid;
181 | }
182 |
183 | public Builder didKeyHolder(DidKeyHolder keyHolder) {
184 | this.issuerBuilder.algorithm(keyHolder.getType().getName())
185 | .keyId(keyHolder.getKeyId())
186 | .did(keyHolder.getDid());
187 | return this;
188 | }
189 |
190 | public Builder algorithm(String algorithm) {
191 | this.issuerBuilder.algorithm(algorithm);
192 | return this;
193 | }
194 |
195 | public Builder keyId(String algorithm) {
196 | this.issuerBuilder.keyId(algorithm);
197 | return this;
198 | }
199 |
200 | public Builder did(String did) {
201 | this.issuerBuilder.did(did);
202 | return this;
203 | }
204 |
205 | public Builder nonce(String nonce) {
206 | this.nonce = nonce;
207 | return this;
208 | }
209 |
210 | public Builder version(String version) {
211 | this.version = version;
212 | return this;
213 | }
214 |
215 | public Builder credentials(List val) {
216 | credentials = val;
217 | return this;
218 | }
219 |
220 | public Presentation build() {
221 | if (issuerDid == null) {
222 | issuerDid = issuerBuilder.build();
223 | }
224 | IssuerDid.Builder.checkArgument(issuerDid, "issuerDid not found");
225 |
226 | Presentation presentation = new Presentation(this.issuerDid);
227 | presentation.nonce = nonce;
228 | if (credentials != null) {
229 | presentation.setCredentials(credentials);
230 | }
231 |
232 | return presentation;
233 | }
234 | }
235 |
236 | public IssuerDid getIssuerDid() {
237 | return issuerDid;
238 | }
239 |
240 | public List getCredentials() {
241 | return credentials;
242 | }
243 |
244 | @Override
245 | public String toString() {
246 | return "Presentation{" +
247 | "issuerDid=" + issuerDid +
248 | ", types=" + types +
249 | ", credentials=" + credentials +
250 | ", nonce='" + nonce + '\'' +
251 | ", jti='" + jti + '\'' +
252 | '}';
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/Algorithm.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.exceptions.KeyPairException;
5 |
6 | import java.security.*;
7 | import java.security.spec.InvalidKeySpecException;
8 | import java.security.spec.PKCS8EncodedKeySpec;
9 | import java.security.spec.X509EncodedKeySpec;
10 |
11 | /**
12 | * This interface use in the Signing or Verification process of a icon-DID.
13 | */
14 | public interface Algorithm {
15 |
16 | /**
17 | * Get the type of Algorithm
18 | *
19 | * @return the Type object
20 | */
21 | AlgorithmProvider.Type getType();
22 |
23 | /**
24 | * Sign the given data using this Algorithm instance and the privateKey.
25 | *
26 | * @param privateKey the privateKey object
27 | * @param data an array of bytes representing the base64 encoded content to be verified against the signature.
28 | * @return the signature bytes
29 | */
30 | byte[] sign(PrivateKey privateKey, byte[] data) throws AlgorithmException;
31 |
32 | /**
33 | * Verify the given token using this Algorithm instance.
34 | *
35 | * @param publicKey the publicKey object to use in the verify
36 | * @param data the array of bytes used for signing
37 | * @param signature the signature bytes
38 | * @return if the signature is valid, return true, or return false
39 | */
40 | boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException;
41 |
42 | /**
43 | * Create a KeyProvider object.
44 | *
45 | * This will generate a new public/private key every time it is called.
46 | * and return the id of key, the type of this algorithm instance and the new public/private key.
47 | *
48 | * @param keyId the id of the key to use in the DID document
49 | * @return the KeyProvider object
50 | */
51 | default KeyProvider generateKeyProvider(String keyId) throws AlgorithmException {
52 | try {
53 | KeyPair keyPair = generateKeyPair();
54 | return new KeyProvider.Builder()
55 | .keyId(keyId)
56 | .publicKey(keyPair.getPublic())
57 | .privateKey(keyPair.getPrivate())
58 | .type(getType())
59 | .build();
60 | } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
61 | throw new AlgorithmException(e);
62 | }
63 | }
64 |
65 | KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException;
66 |
67 | /**
68 | * Sign the given data using the Signature instance and the privateKey.
69 | * {@linkplain java.security.Signature}
70 | *
71 | * @param algorithm the name of algorithm
72 | * @param privateKey the privateKey object to use in the signing
73 | * @param data an array of bytes representing the base64 encoded content to be verified against the signature.
74 | * @return the signature bytes
75 | */
76 | default byte[] signWithSignature(String algorithm, PrivateKey privateKey, byte[] data) throws AlgorithmException {
77 | try {
78 | Signature sig = Signature.getInstance(algorithm);
79 | sig.initSign(privateKey);
80 | sig.update(data);
81 | return sig.sign();
82 | } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
83 | throw new AlgorithmException(e);
84 | }
85 |
86 | }
87 |
88 | /**
89 | * Verify the given token using the Signature instance.
90 | * {@linkplain java.security.Signature}
91 | *
92 | * @param algorithm the name of algorithm
93 | * @param publicKey the publicKey object to use in the verify
94 | * @param data the array of bytes used for signing
95 | * @param signature the signature bytes
96 | * @return if the signature is valid, return true, or return false
97 | */
98 | default boolean verifyWithSignature(String algorithm, PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
99 | try {
100 | Signature sig = Signature.getInstance(algorithm);
101 | sig.initVerify(publicKey);
102 | sig.update(data);
103 | return sig.verify(signature);
104 | } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
105 | throw new AlgorithmException(e);
106 | }
107 |
108 | }
109 |
110 | /**
111 | * Returns the byte array in primary encoding format of the publicKey object.
112 | * {@linkplain #byteToPublicKey(byte[])}
113 | *
114 | * @param publicKey the publicKey object returned from {@linkplain #generateKeyProvider(String)}
115 | * @return the byte array in primary encoding format of the publicKey object
116 | */
117 | default byte[] publicKeyToByte(PublicKey publicKey) {
118 | return publicKey.getEncoded();
119 | }
120 |
121 | /**
122 | * Returns the byte array in primary encoding format of the privateKey object.
123 | * {@linkplain #byteToPrivateKey(byte[])}
124 | *
125 | * @param privateKey the privateKey object returned from {@linkplain #generateKeyProvider(String)}
126 | * @return the byte array in primary encoding format of the privateKey object
127 | */
128 | default byte[] privateKeyToByte(PrivateKey privateKey) {
129 | return privateKey.getEncoded();
130 | }
131 |
132 | /**
133 | * Convert the byte array to the PublicKey object.
134 | *
135 | * @param b the byte array returned from {@linkplain #publicKeyToByte(PublicKey)}
136 | * @return the PublicKey object
137 | */
138 | default PublicKey byteToPublicKey(byte[] b) throws KeyPairException {
139 | try {
140 | KeyFactory kf = KeyFactory.getInstance(getType().getKeyAlgorithm());
141 | return kf.generatePublic(new X509EncodedKeySpec(b));
142 | } catch (NoSuchAlgorithmException e) {
143 | throw new KeyPairException("Could not reconstruct the public key, the given algorithm could not be found.");
144 | } catch (InvalidKeySpecException e) {
145 | throw new KeyPairException("Could not reconstruct the public key");
146 | }
147 | }
148 |
149 | /**
150 | * Convert the byte array to the PrivateKey object.
151 | *
152 | * @param b the byte array returned from {@linkplain #privateKeyToByte(PrivateKey)}
153 | * @return the PrivateKey object
154 | */
155 | default PrivateKey byteToPrivateKey(byte[] b) throws KeyPairException {
156 | try {
157 | KeyFactory kf = KeyFactory.getInstance(getType().getKeyAlgorithm());
158 | return kf.generatePrivate(new PKCS8EncodedKeySpec(b));
159 | } catch (NoSuchAlgorithmException e) {
160 | throw new KeyPairException("Could not reconstruct the private key, the given algorithm could not be found.");
161 | } catch (InvalidKeySpecException e) {
162 | throw new KeyPairException("Could not reconstruct the private key");
163 | }
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/AlgorithmProvider.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.icx.crypto.LinuxSecureRandom;
4 | import org.bouncycastle.crypto.RuntimeCryptoException;
5 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
6 |
7 | import java.security.Provider;
8 | import java.security.SecureRandom;
9 | import java.security.Security;
10 |
11 | /**
12 | * This class to create a new algorithm instance
13 | */
14 | public class AlgorithmProvider {
15 |
16 | public static final String PROVIDER = "BC";
17 |
18 | private static final SecureRandom SECURE_RANDOM;
19 | private static int isAndroid = -1;
20 |
21 | public static final double MIN_BOUNCY_CASTLE_VERSION = 1.54;
22 |
23 | static {
24 |
25 | if (isAndroidRuntime()) {
26 | new LinuxSecureRandom();
27 | }
28 |
29 | SECURE_RANDOM = new SecureRandom();
30 |
31 | Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
32 | Provider newProvider = new BouncyCastleProvider();
33 |
34 | if (newProvider.getVersion() < MIN_BOUNCY_CASTLE_VERSION) {
35 | String message = String.format(
36 | "The version of BouncyCastle should be %f or newer", MIN_BOUNCY_CASTLE_VERSION);
37 | throw new RuntimeCryptoException(message);
38 | }
39 |
40 | if (provider != null) {
41 | Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
42 | }
43 |
44 | Security.addProvider(newProvider);
45 |
46 | }
47 |
48 | /**
49 | * Returns the algorithm object for the type
50 | *
51 | * @param type the type object
52 | * @return the algorithm object
53 | */
54 | public static Algorithm create(Type type) {
55 | if (type == null) {
56 | throw new IllegalArgumentException("type cannot be null.");
57 | }
58 | switch (type) {
59 | case RS256:
60 | throw new IllegalArgumentException("Not supported yet.");
61 | case ES256:
62 | throw new IllegalArgumentException("Not supported yet.");
63 | case ES256K:
64 | return new ES256KAlgorithm();
65 | case NONE:
66 | return new NoneAlgorithm();
67 | default:
68 | throw new IllegalArgumentException("cannot create sigAlgorithm for " + type);
69 | }
70 | }
71 |
72 | /**
73 | * Type-safe representation of signature algorithm names as defined in the icon-DID specification
74 | */
75 | public enum Type {
76 | RS256("RsaVerificationKey2018", "SHA256withRSA", "RSA"),
77 | ES256("Secp256r1VerificationKey", "SHA256withECDSA", "EC"),
78 | ES256K("Secp256k1VerificationKey", "SHA256withECDSA", "EC"),
79 | NONE("none", "none", "none");
80 |
81 | private String identifier;
82 | private String sigAlgorithm;
83 | private String keyAlgorithm;
84 |
85 | Type(String identifier, String sigAlgorithm, String keyAlgorithm) {
86 | this.identifier = identifier;
87 | this.sigAlgorithm = sigAlgorithm;
88 | this.keyAlgorithm = keyAlgorithm;
89 | }
90 |
91 | public String getName() {
92 | return name();
93 | }
94 |
95 | public String getIdentifier() {
96 | return identifier;
97 | }
98 |
99 | public String getSigAlgorithm() {
100 | return sigAlgorithm;
101 | }
102 |
103 | public String getKeyAlgorithm() {
104 | return keyAlgorithm;
105 | }
106 |
107 | public static Type fromName(String name) {
108 | if (name != null) {
109 | for (Type t : Type.values()) {
110 | if (name.equalsIgnoreCase(t.getName())) {
111 | return t;
112 | }
113 | }
114 | }
115 | return null;
116 | }
117 |
118 | public static Type fromIdentifier(String identifier) {
119 | if (identifier != null) {
120 | for (Type t : Type.values()) {
121 | if (identifier.equalsIgnoreCase(t.getIdentifier())) {
122 | return t;
123 | }
124 | }
125 | }
126 | return null;
127 | }
128 | }
129 |
130 | public static SecureRandom secureRandom() {
131 | return SECURE_RANDOM;
132 | }
133 |
134 | public static boolean isAndroidRuntime() {
135 | if (isAndroid == -1) {
136 | final String runtime = System.getProperty("java.runtime.name");
137 | isAndroid = (runtime != null && runtime.equals("Android Runtime")) ? 1 : 0;
138 | }
139 | return isAndroid == 1;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/DidKeyHolder.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.jwt.Jwt;
5 | import org.bouncycastle.util.encoders.Hex;
6 |
7 | import java.security.PrivateKey;
8 | import java.util.Arrays;
9 | import java.util.Objects;
10 |
11 | /**
12 | * This class holds the private key corresponding to the publicKey registered in the DID Document.*
13 | *
14 | *
15 | * To find a privateKey that matches a publicKey registered in a block chain,
16 | * it needs the id of DID document and the id of publicKey.
17 | *
18 | * It is responsible for signing Jwt with the privateKey you have.
19 | */
20 | public class DidKeyHolder {
21 |
22 | private String did;
23 | private String keyId;
24 | private AlgorithmProvider.Type type;
25 | private PrivateKey privateKey;
26 |
27 | private DidKeyHolder(Builder builder) {
28 | did = builder.did;
29 | keyId = builder.keyId;
30 | type = builder.type;
31 | privateKey = builder.privateKey;
32 | }
33 |
34 | public String getDid() {
35 | return did;
36 | }
37 |
38 | public String getKeyId() {
39 | return keyId;
40 | }
41 |
42 | public String getKid() {
43 | return did + "#" + keyId;
44 | }
45 |
46 | public AlgorithmProvider.Type getType() {
47 | return type;
48 | }
49 |
50 | public PrivateKey getPrivateKey() {
51 | return privateKey;
52 | }
53 |
54 | /**
55 | * Create a signature and encoded jwt
56 | *
57 | * @param jwt the Jwt object
58 | * @return the encoded jwt
59 | */
60 | public String sign(Jwt jwt) throws AlgorithmException {
61 | return jwt.sign(privateKey);
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | Algorithm algorithm = AlgorithmProvider.create(type);
67 | String priv = (privateKey == null) ? "" :
68 | Hex.toHexString(algorithm.privateKeyToByte(privateKey));
69 | return "DidKeyHolder{" +
70 | "did='" + did + '\'' +
71 | ", keyId='" + keyId + '\'' +
72 | ", type=" + type +
73 | ", privateKey=" + priv +
74 | '}';
75 | }
76 |
77 | @Override
78 | public boolean equals(Object o) {
79 | if (this == o) return true;
80 | if (!(o instanceof DidKeyHolder)) return false;
81 | DidKeyHolder keyHolder = (DidKeyHolder) o;
82 | Algorithm algorithm = AlgorithmProvider.create(type);
83 | return Objects.equals(did, keyHolder.did) &&
84 | Objects.equals(keyId, keyHolder.keyId) &&
85 | type == keyHolder.type &&
86 | Arrays.equals(algorithm.privateKeyToByte(privateKey),
87 | algorithm.privateKeyToByte(keyHolder.privateKey));
88 | }
89 |
90 | @Override
91 | public int hashCode() {
92 | return Objects.hash(did, keyId, type, privateKey);
93 | }
94 |
95 | public static final class Builder {
96 | private String did;
97 | private String keyId;
98 | private AlgorithmProvider.Type type;
99 | private PrivateKey privateKey;
100 |
101 | public Builder() {
102 | }
103 |
104 | public Builder(KeyProvider provider) {
105 | this.keyId = provider.getKeyId();
106 | this.type = provider.getType();
107 | this.privateKey = provider.getPrivateKey();
108 | }
109 |
110 | public Builder did(String val) {
111 | did = val;
112 | return this;
113 | }
114 |
115 | public Builder keyId(String val) {
116 | keyId = val;
117 | return this;
118 | }
119 |
120 | public Builder type(AlgorithmProvider.Type val) {
121 | type = val;
122 | return this;
123 | }
124 |
125 | public Builder privateKey(PrivateKey val) {
126 | privateKey = val;
127 | return this;
128 | }
129 |
130 | public DidKeyHolder build() {
131 | checkArgument(did, "did not found");
132 | checkArgument(privateKey, "privateKey not found");
133 | checkArgument(keyId, "keyId not found");
134 | checkArgument(type, "type not found");
135 |
136 | return new DidKeyHolder(this);
137 | }
138 |
139 | public static void checkArgument(T object, String message) {
140 | if (object == null) {
141 | throw new IllegalArgumentException(message);
142 | }
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/ES256Algorithm.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.exceptions.JwtException;
5 | import org.bouncycastle.asn1.ASN1InputStream;
6 | import org.bouncycastle.asn1.ASN1Integer;
7 | import org.bouncycastle.asn1.DERSequenceGenerator;
8 | import org.bouncycastle.asn1.DLSequence;
9 | import org.bouncycastle.util.BigIntegers;
10 |
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.IOException;
13 | import java.math.BigInteger;
14 | import java.nio.ByteBuffer;
15 | import java.security.*;
16 | import java.security.spec.ECGenParameterSpec;
17 |
18 | import static foundation.icon.did.core.AlgorithmProvider.PROVIDER;
19 | import static foundation.icon.did.core.AlgorithmProvider.secureRandom;
20 | import static foundation.icon.did.core.PropertyName.EC_CURVE_PARAM_SECP256R1;
21 |
22 | public class ES256Algorithm implements Algorithm {
23 |
24 | public static final int EC_256_NUMBER = 32;
25 | private AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
26 |
27 | ES256Algorithm() {
28 | }
29 |
30 | @Override
31 | public AlgorithmProvider.Type getType() {
32 | return type;
33 | }
34 |
35 | @Override
36 | public KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
37 | KeyPairGenerator pairGen = KeyPairGenerator.getInstance("EC", PROVIDER);
38 | pairGen.initialize(new ECGenParameterSpec(EC_CURVE_PARAM_SECP256R1), secureRandom());
39 | return pairGen.generateKeyPair();
40 | }
41 |
42 | @Override
43 | public byte[] sign(PrivateKey privateKey, byte[] data) throws AlgorithmException {
44 | byte[] signature = signWithSignature(type.getSigAlgorithm(), privateKey, data);
45 | return ecDerDecode(signature, EC_256_NUMBER);
46 | }
47 |
48 | @Override
49 | public boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
50 | try {
51 | signature = ecDerEncode(signature, EC_256_NUMBER);
52 | } catch (IOException e) {
53 | throw new JwtException(e.getMessage(), e.getCause());
54 | }
55 | return verifyWithSignature(type.getSigAlgorithm(), publicKey, data, signature);
56 | }
57 |
58 | static byte[] ecDerDecode(byte[] signature, int ecNumberSize) {
59 | try (ASN1InputStream decoder = new ASN1InputStream(signature)) {
60 | DLSequence seq = (DLSequence) decoder.readObject();
61 | ASN1Integer r = (ASN1Integer) seq.getObjectAt(0);
62 | ASN1Integer s = (ASN1Integer) seq.getObjectAt(1);
63 |
64 | ByteBuffer buffer = ByteBuffer.allocate(ecNumberSize * 2);
65 | buffer.put(BigIntegers.asUnsignedByteArray(ecNumberSize, r.getValue()));
66 | buffer.put(BigIntegers.asUnsignedByteArray(ecNumberSize, s.getValue()));
67 | return buffer.array();
68 | } catch (IOException e) {
69 | throw new RuntimeException(e);
70 | }
71 | }
72 |
73 | static byte[] ecDerEncode(byte[] signature, int ecNumberSize) throws IOException {
74 | byte[] r = new byte[ecNumberSize];
75 | byte[] s = new byte[ecNumberSize];
76 | System.arraycopy(signature, 0, r, 0, ecNumberSize);
77 | System.arraycopy(signature, ecNumberSize, s, 0, ecNumberSize);
78 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
79 | DERSequenceGenerator seq = new DERSequenceGenerator(baos);
80 | seq.addObject(new ASN1Integer(new BigInteger(1, r)));
81 | seq.addObject(new ASN1Integer(new BigInteger(1, s)));
82 | seq.close();
83 | return baos.toByteArray();
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/ES256KAlgorithm.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.exceptions.KeyPairException;
5 | import foundation.icon.icx.crypto.ECDSASignature;
6 | import foundation.icon.icx.crypto.IconKeys;
7 | import foundation.icon.icx.data.Bytes;
8 | import org.bouncycastle.crypto.params.ECDomainParameters;
9 | import org.bouncycastle.crypto.params.ECPublicKeyParameters;
10 | import org.bouncycastle.crypto.signers.ECDSASigner;
11 | import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
12 | import org.bouncycastle.jcajce.provider.digest.SHA3;
13 | import org.bouncycastle.jce.ECNamedCurveTable;
14 | import org.bouncycastle.jce.interfaces.ECPublicKey;
15 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
16 | import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
17 | import org.bouncycastle.jce.spec.ECParameterSpec;
18 | import org.bouncycastle.jce.spec.ECPrivateKeySpec;
19 | import org.bouncycastle.jce.spec.ECPublicKeySpec;
20 | import org.bouncycastle.util.BigIntegers;
21 |
22 | import java.math.BigInteger;
23 | import java.security.*;
24 | import java.security.spec.ECGenParameterSpec;
25 | import java.security.spec.InvalidKeySpecException;
26 | import java.util.Arrays;
27 |
28 | import static foundation.icon.did.core.AlgorithmProvider.PROVIDER;
29 | import static foundation.icon.did.core.AlgorithmProvider.secureRandom;
30 | import static foundation.icon.did.core.PropertyName.EC_CURVE_PARAM_SECP256K1;
31 |
32 | public class ES256KAlgorithm implements Algorithm {
33 |
34 | private AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256K;
35 |
36 | private ECNamedCurveParameterSpec spec;
37 | private ECParameterSpec ecparameterSpec;
38 |
39 | ES256KAlgorithm() {
40 | spec = ECNamedCurveTable.getParameterSpec("secp256k1");
41 | ecparameterSpec = new ECParameterSpec(spec.getCurve(), spec.getG(), spec.getN());
42 | }
43 |
44 | @Override
45 | public AlgorithmProvider.Type getType() {
46 | return type;
47 | }
48 |
49 | @Override
50 | public KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
51 | KeyPairGenerator pairGen = KeyPairGenerator.getInstance("EC", PROVIDER);
52 | pairGen.initialize(new ECGenParameterSpec(EC_CURVE_PARAM_SECP256K1), secureRandom());
53 | return pairGen.generateKeyPair();
54 | }
55 |
56 | @Override
57 | public byte[] sign(PrivateKey privateKey, byte[] data) throws AlgorithmException {
58 | Bytes p = new Bytes(privateKeyToByte(privateKey));
59 | ECDSASignature signature = new ECDSASignature(p);
60 | byte[] hash = new SHA3.Digest256().digest(data);
61 | BigInteger[] sig = signature.generateSignature(hash);
62 | return signature.recoverableSerialize(sig, hash);
63 | }
64 |
65 | @Override
66 | public boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
67 | try {
68 | byte[] pub = ((ECPublicKey) publicKey).getQ().getEncoded(false);
69 | byte[] sigr = Arrays.copyOfRange(signature, 0, ES256Algorithm.EC_256_NUMBER);
70 | byte[] sigs = Arrays.copyOfRange(signature, ES256Algorithm.EC_256_NUMBER, ES256Algorithm.EC_256_NUMBER * 2);
71 |
72 | ECDomainParameters domain = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN());
73 | ECPublicKeyParameters publicKeyParams =
74 | new ECPublicKeyParameters(spec.getCurve().decodePoint(pub), domain);
75 |
76 | ECDSASigner signer = new ECDSASigner();
77 | signer.init(false, publicKeyParams);
78 | byte[] hash = new SHA3.Digest256().digest(data);
79 | return signer.verifySignature(hash, new BigInteger(1, sigr), new BigInteger(1, sigs));
80 | } catch (Exception e) {
81 | return false;
82 | }
83 | }
84 |
85 | @Override
86 | public byte[] publicKeyToByte(PublicKey publicKey) {
87 | return ((ECPublicKey) publicKey).getQ().getEncoded(false);
88 | }
89 |
90 | @Override
91 | public byte[] privateKeyToByte(PrivateKey privateKey) {
92 | return BigIntegers.asUnsignedByteArray(IconKeys.PRIVATE_KEY_SIZE, ((BCECPrivateKey) privateKey).getD());
93 | }
94 |
95 | @Override
96 | public PublicKey byteToPublicKey(byte[] b) throws KeyPairException {
97 | try {
98 | KeyFactory fact = KeyFactory.getInstance(type.getKeyAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
99 | return fact.generatePublic(new ECPublicKeySpec(spec.getCurve().decodePoint(b), ecparameterSpec));
100 | } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
101 | throw new KeyPairException("Could not reconstruct the public key, the given algorithm could not be found.");
102 | } catch (InvalidKeySpecException e) {
103 | throw new KeyPairException("Could not reconstruct the public key");
104 | }
105 | }
106 |
107 | @Override
108 | public PrivateKey byteToPrivateKey(byte[] b) throws KeyPairException {
109 | try {
110 | KeyFactory fact = KeyFactory.getInstance(type.getKeyAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
111 | return fact.generatePrivate(new ECPrivateKeySpec(new BigInteger(1, b), ecparameterSpec));
112 | } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
113 | throw new KeyPairException("Could not reconstruct the private key, the given algorithm could not be found.");
114 | } catch (InvalidKeySpecException e) {
115 | throw new KeyPairException("Could not reconstruct the private key");
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/KeyProvider.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import org.bouncycastle.util.encoders.Hex;
4 |
5 | import java.security.PrivateKey;
6 | import java.security.PublicKey;
7 | import java.util.Arrays;
8 | import java.util.Objects;
9 |
10 | /**
11 | * Generic Public/Private Key provider.
12 | * {@linkplain Algorithm#generateKeyProvider(String)}
13 | */
14 | public class KeyProvider {
15 | private String keyId;
16 | private AlgorithmProvider.Type type;
17 | private PublicKey publicKey;
18 | private PrivateKey privateKey;
19 |
20 | private KeyProvider(Builder builder) {
21 | keyId = builder.keyId;
22 | type = builder.type;
23 | publicKey = builder.publicKey;
24 | privateKey = builder.privateKey;
25 | }
26 |
27 | public String getKeyId() {
28 | return keyId;
29 | }
30 |
31 | public AlgorithmProvider.Type getType() {
32 | return type;
33 | }
34 |
35 | public PublicKey getPublicKey() {
36 | return publicKey;
37 | }
38 |
39 | public PrivateKey getPrivateKey() {
40 | return privateKey;
41 | }
42 |
43 | public Builder newBuilder() {
44 | return new Builder(this);
45 | }
46 |
47 | public static final class Builder {
48 | private String keyId;
49 | private AlgorithmProvider.Type type;
50 | private PublicKey publicKey;
51 | private PrivateKey privateKey;
52 |
53 | public Builder() {
54 | }
55 |
56 | public Builder(KeyProvider keyProvider) {
57 | keyId = keyProvider.keyId;
58 | type = keyProvider.type;
59 | publicKey = keyProvider.publicKey;
60 | privateKey = keyProvider.privateKey;
61 | }
62 |
63 | public Builder keyId(String val) {
64 | keyId = val;
65 | return this;
66 | }
67 |
68 | public Builder type(AlgorithmProvider.Type val) {
69 | type = val;
70 | return this;
71 | }
72 |
73 | public Builder publicKey(PublicKey val) {
74 | publicKey = val;
75 | return this;
76 | }
77 |
78 | public Builder privateKey(PrivateKey val) {
79 | privateKey = val;
80 | return this;
81 | }
82 |
83 | public KeyProvider build() {
84 | if (keyId == null) throw new IllegalArgumentException("keyId cannot be null.");
85 | if (type == null) throw new IllegalArgumentException("type cannot be null.");
86 | return new KeyProvider(this);
87 | }
88 | }
89 |
90 | @Override
91 | public String toString() {
92 | Algorithm algorithm = AlgorithmProvider.create(type);
93 | String pub = (publicKey == null) ? "" :
94 | Hex.toHexString(algorithm.publicKeyToByte(publicKey));
95 | String priv = (privateKey == null) ? "" :
96 | Hex.toHexString(algorithm.privateKeyToByte(privateKey));
97 | return "KeyProvider{" +
98 | "keyId='" + keyId + '\'' +
99 | ", type=" + type +
100 | ", publicKey=" + pub +
101 | ", privateKey=" + priv +
102 | '}';
103 | }
104 |
105 | @Override
106 | public boolean equals(Object o) {
107 | if (this == o) return true;
108 | if (!(o instanceof KeyProvider)) return false;
109 | KeyProvider that = (KeyProvider) o;
110 |
111 | Algorithm algorithm = AlgorithmProvider.create(type);
112 |
113 | return Objects.equals(keyId, that.keyId) &&
114 | type == that.type &&
115 | Arrays.equals(algorithm.publicKeyToByte(publicKey),
116 | algorithm.publicKeyToByte(that.publicKey)) &&
117 | Arrays.equals(algorithm.privateKeyToByte(privateKey),
118 | algorithm.privateKeyToByte(that.privateKey));
119 | }
120 |
121 | @Override
122 | public int hashCode() {
123 | Algorithm algorithm = AlgorithmProvider.create(type);
124 | return Objects.hash(keyId, type.name(),
125 | algorithm.publicKeyToByte(publicKey),
126 | algorithm.privateKeyToByte(privateKey));
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/NoneAlgorithm.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.exceptions.KeyPairException;
5 |
6 | import java.security.*;
7 |
8 | public class NoneAlgorithm implements Algorithm {
9 |
10 | private AlgorithmProvider.Type type = AlgorithmProvider.Type.NONE;
11 |
12 | @Override
13 | public AlgorithmProvider.Type getType() {
14 | return type;
15 | }
16 |
17 | @Override
18 | public KeyProvider generateKeyProvider(String keyId) throws AlgorithmException {
19 | return null;
20 | }
21 |
22 | @Override
23 | public KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
24 | return null;
25 | }
26 |
27 | @Override
28 | public byte[] signWithSignature(String algorithm, PrivateKey privateKey, byte[] data) throws AlgorithmException {
29 | return new byte[0];
30 | }
31 |
32 | @Override
33 | public boolean verifyWithSignature(String algorithm, PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
34 | return true;
35 | }
36 |
37 | @Override
38 | public byte[] publicKeyToByte(PublicKey publicKey) {
39 | return new byte[0];
40 | }
41 |
42 | @Override
43 | public byte[] privateKeyToByte(PrivateKey privateKey) {
44 | return new byte[0];
45 | }
46 |
47 | @Override
48 | public PublicKey byteToPublicKey(byte[] b) throws KeyPairException {
49 | return null;
50 | }
51 |
52 | @Override
53 | public PrivateKey byteToPrivateKey(byte[] b) throws KeyPairException {
54 | return null;
55 | }
56 |
57 | @Override
58 | public byte[] sign(PrivateKey privateKey, byte[] data) throws AlgorithmException {
59 | return new byte[0];
60 | }
61 |
62 | @Override
63 | public boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
64 | return true;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/PropertyName.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | public class PropertyName {
4 |
5 | private PropertyName() {
6 | }
7 |
8 | public static final String ALGO_KEY_RSA = "RS256";
9 | public static final String ALGO_KEY_ECDSA = "ES256";
10 | public static final String ALGO_KEY_ECDSAK = "ES256K";
11 |
12 | public static final String EC_CURVE_PARAM_SECP256R1 = "secp256r1";
13 | public static final String EC_CURVE_PARAM_SECP256K1 = "secp256k1";
14 |
15 | public static final String KEY_DOCUMENT_CONTEXT = "@context";
16 | public static final String KEY_VERSION = "version";
17 | public static final String KEY_DOCUMENT_ID = "id";
18 | public static final String KEY_DOCUMENT_CREATED = "created";
19 | public static final String KEY_DOCUMENT_UPDATED = "updated";
20 | public static final String KEY_DOCUMENT_PUBLICKEY = "publicKey";
21 | public static final String KEY_DOCUMENT_PUBLICKEY_ID = "id";
22 | public static final String KEY_DOCUMENT_PUBLICKEY_TYPE = "type";
23 | public static final String KEY_DOCUMENT_PUBLICKEY_HEX = "publicKeyHex";
24 | public static final String KEY_DOCUMENT_PUBLICKEY_BASE64 = "publicKeyBase64";
25 | public static final String KEY_DOCUMENT_PUBLICKEY_CREATED = "created";
26 | public static final String KEY_DOCUMENT_PUBLICKEY_REVOKED = "revoked";
27 | public static final String KEY_DOCUMENT_AUTHENTICATION = "authentication";
28 | public static final String KEY_DOCUMENT_AUTHENTICATION_PUBLICKEY = "publicKey";
29 | public static final String KEY_DOCUMENT_AUTHENTICATION_TYPE = "type";
30 |
31 | public static final String VALUE_DOCUMENT_CONTEXT = "https://w3id.org/did/v1";
32 |
33 | // Update Transaction
34 | public static final String KEY_TX_UPDATE_METHOD = "method";
35 | public static final String KEY_TX_UPDATE_METHOD_ADDKEY = "addKey";
36 | public static final String KEY_TX_UPDATE_METHOD_REVOKEKEY = "revokeKey";
37 | public static final String KEY_TX_UPDATE_PARAM = "param";
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/core/RS256Algorithm.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 |
5 | import java.security.*;
6 |
7 | import static foundation.icon.did.core.AlgorithmProvider.PROVIDER;
8 | import static foundation.icon.did.core.AlgorithmProvider.secureRandom;
9 |
10 | public class RS256Algorithm implements Algorithm {
11 |
12 | private AlgorithmProvider.Type type = AlgorithmProvider.Type.RS256;
13 |
14 | RS256Algorithm() {
15 | }
16 |
17 | @Override
18 | public AlgorithmProvider.Type getType() {
19 | return type;
20 | }
21 |
22 | @Override
23 | public KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
24 | KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", PROVIDER);
25 | gen.initialize(2048, secureRandom());
26 | return gen.generateKeyPair();
27 | }
28 |
29 | @Override
30 | public byte[] sign(PrivateKey privateKey, byte[] data) throws AlgorithmException {
31 | return signWithSignature(type.getSigAlgorithm(), privateKey, data);
32 | }
33 |
34 | @Override
35 | public boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws AlgorithmException {
36 | return verifyWithSignature(type.getSigAlgorithm(), publicKey, data, signature);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/document/AuthenticationProperty.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.document;
2 |
3 | /**
4 | * This corresponds to the authentication property of the DIDs specification.
5 | * https://w3c-ccg.github.io/did-spec/#authentication
6 | */
7 | public class AuthenticationProperty {
8 | String type;
9 | String publicKey;
10 |
11 | private AuthenticationProperty(Builder builder) {
12 | type = builder.type;
13 | publicKey = builder.publicKey;
14 | }
15 |
16 | public String getType() {
17 | return type;
18 | }
19 |
20 | public String getPublicKey() {
21 | return publicKey;
22 | }
23 |
24 | public static final class Builder {
25 | private String type;
26 | private String publicKey;
27 |
28 | public Builder() {
29 | }
30 |
31 | public Builder type(String val) {
32 | type = val;
33 | return this;
34 | }
35 |
36 | public Builder publicKey(String val) {
37 | publicKey = val;
38 | return this;
39 | }
40 |
41 | public AuthenticationProperty build() {
42 | return new AuthenticationProperty(this);
43 | }
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return "AuthenticationProperty{" +
49 | "type=" + type +
50 | ", publicKey='" + publicKey + '\'' +
51 | '}';
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/document/Document.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.document;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 |
6 | /**
7 | * This corresponds to the publicKeys property of the DIDs specification.
8 | * https://w3c-ccg.github.io/did-spec/#did-documents
9 | */
10 | public class Document {
11 | private String version;
12 | private String id;
13 | private long created;
14 | private long updated;
15 | private Map publicKey;
16 | private List authentication;
17 |
18 | private Document(Builder builder) {
19 | version = builder.version;
20 | id = builder.id;
21 | created = builder.created;
22 | updated = builder.updated;
23 | publicKey = builder.publicKey;
24 | authentication = builder.authentication;
25 | }
26 |
27 | public String getVersion() { return version; }
28 |
29 | public String getId() {
30 | return id;
31 | }
32 |
33 | public long getCreated() {
34 | return created;
35 | }
36 |
37 | public long getUpdated() {
38 | return updated;
39 | }
40 |
41 | public Map getPublicKeyProperty() {
42 | return publicKey;
43 | }
44 |
45 | public PublicKeyProperty getPublicKeyProperty(String publicKeyId) {
46 | return publicKey.get(publicKeyId);
47 | }
48 |
49 | public List getAuthentication() {
50 | return authentication;
51 | }
52 |
53 | public String toJson() {
54 | return Converters.gson().toJson(this);
55 | }
56 |
57 |
58 | public static final class Builder {
59 | private String version;
60 | private String id;
61 | private long created;
62 | private long updated;
63 | private Map publicKey;
64 | private List authentication;
65 |
66 | public Builder() {
67 | }
68 |
69 | public Builder version(String val) {
70 | version = val;
71 | return this;
72 | }
73 |
74 | public Builder id(String val) {
75 | id = val;
76 | return this;
77 | }
78 |
79 | public Builder created(long val) {
80 | created = val;
81 | return this;
82 | }
83 |
84 | public Builder updated(long val) {
85 | updated = val;
86 | return this;
87 | }
88 |
89 | public Builder publicKey(Map val) {
90 | publicKey = val;
91 | return this;
92 | }
93 |
94 | public Builder authentication(List val) {
95 | authentication = val;
96 | return this;
97 | }
98 |
99 | public Document build() {
100 | return new Document(this);
101 | }
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return "Document{" +
107 | " id='" + id + '\'' +
108 | ", created=" + created +
109 | ", updated=" + updated +
110 | ", publicKey=" + publicKey +
111 | ", authentication=" + authentication +
112 | '}';
113 | }
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/document/EncodeType.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.document;
2 |
3 | import org.bouncycastle.util.encoders.Base64;
4 | import org.bouncycastle.util.encoders.Hex;
5 |
6 | public enum EncodeType implements Encoder {
7 | HEX("publicKeyHex") {
8 | public String encode(byte[] data) {
9 | return Hex.toHexString(data);
10 | }
11 |
12 | public byte[] decode(String data) {
13 | return Hex.decode(data);
14 | }
15 | },
16 | BASE64("publicKeyBase64") {
17 | public String encode(byte[] data) {
18 | return Base64.toBase64String(data);
19 | }
20 |
21 | public byte[] decode(String data) {
22 | return Base64.decode(data);
23 | }
24 | };
25 |
26 | private String name;
27 |
28 | EncodeType(String name) {
29 | this.name = name;
30 | }
31 |
32 | public String getValue() {
33 | return name;
34 | }
35 |
36 | public static EncodeType fromString(String type) {
37 | if (type != null) {
38 | for (EncodeType t : EncodeType.values()) {
39 | if (type.equalsIgnoreCase(t.getValue())) {
40 | return t;
41 | }
42 | }
43 | }
44 | return null;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/document/Encoder.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.document;
2 |
3 | public interface Encoder {
4 | String encode(byte[] data);
5 | byte[] decode(String data);
6 | }
7 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/document/PublicKeyProperty.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.document;
2 |
3 | import foundation.icon.did.core.Algorithm;
4 | import foundation.icon.did.core.AlgorithmProvider;
5 |
6 | import java.security.PublicKey;
7 | import java.util.List;
8 |
9 | /**
10 | * This corresponds to the publicKeys property of the DIDs specification.
11 | * https://w3c-ccg.github.io/did-spec/#public-keys
12 | */
13 | public class PublicKeyProperty {
14 |
15 | private String id;
16 | private PublicKey publicKey;
17 | private List type;
18 | private EncodeType encodeType;
19 | private long created;
20 | private long revoked;
21 |
22 | private PublicKeyProperty(Builder builder) {
23 | id = builder.id;
24 | publicKey = builder.publicKey;
25 | type = builder.type;
26 | encodeType = builder.encodeType;
27 | created = builder.created;
28 | revoked = builder.revoked;
29 | }
30 |
31 | public String getId() {
32 | return id;
33 | }
34 |
35 | public List getType() {
36 | return type;
37 | }
38 |
39 | public AlgorithmProvider.Type getAlgorithmType() {
40 | return AlgorithmProvider.Type.fromIdentifier(type.get(0));
41 | }
42 |
43 | public long getCreated() {
44 | return created;
45 | }
46 |
47 | public long getRevoked() {
48 | return revoked;
49 | }
50 |
51 | public PublicKey getPublicKey() {
52 | return publicKey;
53 | }
54 |
55 | public EncodeType getEncodeType() {
56 | return encodeType;
57 | }
58 |
59 | public boolean isRevoked() {
60 | return (revoked > 0);
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | Algorithm algorithm = AlgorithmProvider.create(getAlgorithmType());
66 | String pub = encodeType.encode(algorithm.publicKeyToByte(publicKey));
67 | return "PublicKeyProperty{" +
68 | "id='" + id + '\'' +
69 | ", publicKey=" + pub +
70 | ", type='" + type + '\'' +
71 | ", encodeType=" + encodeType +
72 | ", created=" + created +
73 | ", revoked=" + revoked +
74 | '}';
75 | }
76 |
77 |
78 | public static final class Builder {
79 | private String id;
80 | private PublicKey publicKey;
81 | private List type;
82 | private EncodeType encodeType;
83 | private long created;
84 | private long revoked;
85 |
86 | public Builder() {
87 | }
88 |
89 | public Builder id(String val) {
90 | id = val;
91 | return this;
92 | }
93 |
94 | public Builder publicKey(PublicKey val) {
95 | publicKey = val;
96 | return this;
97 | }
98 |
99 | public Builder type(List val) {
100 | type = val;
101 | return this;
102 | }
103 |
104 | public Builder encodeType(EncodeType val) {
105 | encodeType = val;
106 | return this;
107 | }
108 |
109 | public Builder created(long val) {
110 | created = val;
111 | return this;
112 | }
113 |
114 | public Builder revoked(long val) {
115 | revoked = val;
116 | return this;
117 | }
118 |
119 | public PublicKeyProperty build() {
120 | if (id == null) throw new IllegalArgumentException("id cannot be null.");
121 | if (type == null) throw new IllegalArgumentException("type cannot be null.");
122 | if (publicKey == null) throw new IllegalArgumentException("publicKey cannot be null.");
123 | return new PublicKeyProperty(this);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/AlgorithmException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 | import java.security.GeneralSecurityException;
4 |
5 | public class AlgorithmException extends GeneralSecurityException {
6 |
7 | public AlgorithmException(String message) {
8 | super(message);
9 | }
10 |
11 | public AlgorithmException(String message, Throwable cause) {
12 | super(message, cause);
13 | }
14 |
15 | public AlgorithmException(Throwable cause) {
16 | super(cause);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/JwtException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 | public class JwtException extends RuntimeException {
4 |
5 | public JwtException(String message) {
6 | super(message);
7 | }
8 |
9 | public JwtException(String message, Throwable cause) {
10 | super(message, cause);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/KeyPairException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 | import java.security.GeneralSecurityException;
4 |
5 | public class KeyPairException extends GeneralSecurityException {
6 | public KeyPairException(String msg) {
7 | super(msg);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/KeystoreException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 | /**
4 | * Original Code
5 | * https://github.com/web3j/web3j/blob/master/crypto/src/main/java/org/web3j/crypto/CipherException.java
6 | */
7 | public class KeystoreException extends Exception {
8 |
9 | public KeystoreException(String message) {
10 | super(message);
11 | }
12 |
13 | KeystoreException(Throwable cause) {
14 | super(cause);
15 | }
16 |
17 | public KeystoreException(String message, Throwable cause) {
18 | super(message, cause);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/ResolveException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 |
4 | public class ResolveException extends RuntimeException {
5 |
6 | public ResolveException(String message) {
7 | super(message);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/exceptions/TransactionException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exceptions;
2 |
3 | import foundation.icon.icx.data.TransactionResult;
4 |
5 | public class TransactionException extends RuntimeException {
6 | private static String getMessage(TransactionResult result) {
7 | String message = "Fail transaction !! txHash:" + result.getTxHash();
8 | TransactionResult.Failure failure = result.getFailure();
9 | if (failure != null) {
10 | message = message + "\n" + failure.getMessage();
11 | }
12 | return message;
13 | }
14 |
15 | public TransactionException(String message) {
16 | super(message);
17 | }
18 |
19 | public TransactionException(TransactionResult result) {
20 | super(getMessage(result));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/jwt/ConvertJwt.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.jwt;
2 |
3 | import foundation.icon.did.Credential;
4 | import foundation.icon.did.Presentation;
5 |
6 | import java.util.Date;
7 |
8 | /**
9 | * A interface to convert {@linkplain Credential} and {@linkplain Presentation} to 'Json Web Token'
10 | */
11 | public interface ConvertJwt {
12 |
13 | /**
14 | * The time in seconds from the issued time to expiration
15 | *
16 | * @return the duration in seconds
17 | */
18 | int getDuration();
19 |
20 | /**
21 | * Create a new JWT with default iat and exp
22 | *
23 | * default iat : the current time
24 | * default exp : default iat + {@code getDuration()}
25 | *
26 | * @return the Jwt object
27 | */
28 | default Jwt buildJwt() {
29 | Date issued = new Date();
30 | long duration = getDuration() * 1000L; // to milliseconds
31 | Date expiration = new Date(issued.getTime() + duration);
32 | return buildJwt(issued, expiration);
33 | }
34 |
35 | /**
36 | * Create a new JWT
37 | *
38 | * @param issued the time at which the JWT was issued
39 | * @param expiration the time at which the JWT must not be accepted for processing
40 | * @return the JWT object
41 | */
42 | Jwt buildJwt(Date issued, Date expiration);
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/jwt/Header.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.jwt;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 |
5 | import java.util.Objects;
6 |
7 | @JsonInclude(JsonInclude.Include.NON_NULL)
8 | public class Header {
9 | // header
10 | private String alg;
11 | private String kid;
12 |
13 | private Header(Builder builder) {
14 | alg = builder.alg;
15 | kid = builder.kid;
16 | }
17 |
18 | public String getAlg() {
19 | return alg;
20 | }
21 |
22 | public String getKid() {
23 | return kid;
24 | }
25 |
26 |
27 |
28 | @Override
29 | public String toString() {
30 | return "Header{" +
31 | "alg='" + alg + '\'' +
32 | ", kid='" + kid + '\'' +
33 | '}';
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (this == o) return true;
39 | if (!(o instanceof Header)) return false;
40 | Header header = (Header) o;
41 | return Objects.equals(alg, header.alg) &&
42 | Objects.equals(kid, header.kid);
43 | }
44 |
45 | @Override
46 | public int hashCode() {
47 | return Objects.hash(alg, kid);
48 | }
49 |
50 | public static final class Builder {
51 | private String alg;
52 | private String kid;
53 |
54 | public Builder() {
55 | }
56 |
57 | public Builder alg(String val) {
58 | alg = val;
59 | return this;
60 | }
61 |
62 | public Builder kid(String val) {
63 | kid = val;
64 | return this;
65 | }
66 |
67 | public Header build() {
68 | return new Header(this);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/jwt/IssuerDid.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.jwt;
2 |
3 |
4 | import foundation.icon.did.core.DidKeyHolder;
5 |
6 | import java.util.Date;
7 |
8 | /**
9 | * This class holds DID-related information of the issuer in JWT.
10 | *
11 | * We can get this information from the JWT header.
12 | */
13 | public class IssuerDid implements ConvertJwt {
14 |
15 | private final static int EXP_DURATION = 5 * 60; // seconds
16 |
17 | private String did;
18 | private String algorithm;
19 | private String keyId;
20 |
21 | IssuerDid(String did, String algorithm, String keyId) {
22 | this.did = did;
23 | this.algorithm = algorithm;
24 | this.keyId = keyId;
25 | }
26 |
27 | @Override
28 | public int getDuration() {
29 | return EXP_DURATION;
30 | }
31 |
32 | /**
33 | * Create a new JWT
34 | *
35 | * @param issued 토큰 발급 시간
36 | * @param expiration 토큰 만료 시간
37 | * @return a Jwt
38 | */
39 | @Override
40 | public Jwt buildJwt(Date issued, Date expiration) {
41 | String kid = did + "#" + keyId;
42 | return new Jwt.Builder()
43 | .alg(algorithm)
44 | .kid(kid)
45 | .iss(did)
46 | .iat(issued)
47 | .exp(expiration)
48 | .build();
49 | }
50 |
51 | /**
52 | * Returns the IssuerDid object representation of the String argument.
53 | *
54 | * @param encodedJwt the String returned by calling {@linkplain DidKeyHolder#sign(Jwt)}
55 | * @return the IssuerDid object
56 | */
57 | public static IssuerDid valueOf(String encodedJwt) {
58 | return valueOf(Jwt.decode(encodedJwt));
59 | }
60 |
61 | /**
62 | * Returns the IssuerDid object representation of the Jwt argument.
63 | *
64 | * @param jwt the JWT with properties of the Presentation object
65 | * @return the IssuerDid object
66 | * @see IssuerDid#buildJwt(Date, Date)
67 | */
68 | public static IssuerDid valueOf(Jwt jwt) {
69 | Header header = jwt.getHeader();
70 | String[] kid = header.getKid().split("#");
71 |
72 | return new Builder()
73 | .did(kid[0])
74 | .algorithm(header.getAlg())
75 | .keyId(kid[1])
76 | .build();
77 | }
78 |
79 | public static IssuerDid valueOf(DidKeyHolder didKeyHolder) {
80 | return new Builder()
81 | .did(didKeyHolder.getDid())
82 | .algorithm(didKeyHolder.getType().getName())
83 | .keyId(didKeyHolder.getKeyId())
84 | .build();
85 | }
86 |
87 | public String getDid() {
88 | return did;
89 | }
90 |
91 | public String getAlgorithm() {
92 | return algorithm;
93 | }
94 |
95 | public String getKeyId() {
96 | return keyId;
97 | }
98 |
99 |
100 | public static final class Builder {
101 | private String did;
102 | private String algorithm;
103 | private String keyId;
104 |
105 | public Builder() {
106 | }
107 |
108 | public Builder did(String did) {
109 | this.did = did;
110 | return this;
111 | }
112 |
113 | public Builder algorithm(String algorithm) {
114 | this.algorithm = algorithm;
115 | return this;
116 | }
117 |
118 | public Builder keyId(String keyId) {
119 | this.keyId = keyId;
120 | return this;
121 | }
122 |
123 | public IssuerDid build() {
124 | checkArgument(did, "did not found");
125 | checkArgument(algorithm, "algorithm not found");
126 | checkArgument(keyId, "keyId not found");
127 |
128 | return new IssuerDid(did, algorithm, keyId);
129 | }
130 |
131 | public static void checkArgument(T object, String message) {
132 | if (object == null) {
133 | throw new IllegalArgumentException(message);
134 | }
135 | }
136 | }
137 |
138 | @Override
139 | public String toString() {
140 | return "IssuerDid{" +
141 | "did='" + did + '\'' +
142 | ", algorithm='" + algorithm + '\'' +
143 | ", keyId='" + keyId + '\'' +
144 | '}';
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/jwt/Payload.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.jwt;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 |
5 | import java.util.*;
6 |
7 | @JsonInclude(JsonInclude.Include.NON_NULL)
8 | public class Payload {
9 |
10 | public static final String TYPE = "type";
11 | public static final String ISSUER = "iss";
12 | public static final String SUBJECT = "sub";
13 | public static final String AUDIENCE = "aud";
14 | public static final String ISSUED_AT = "iat";
15 | public static final String EXPIRATION = "exp";
16 | public static final String JTI = "jti";
17 | public static final String CLAIM = "claim";
18 | public static final String CREDENTIAL = "credential";
19 | public static final String NONCE = "nonce";
20 | public static final String VERSION = "version";
21 |
22 | private Map map;
23 | private List timeClaimKeys;
24 |
25 | Payload() {
26 | map = new TreeMap<>();
27 | timeClaimKeys = new ArrayList<>();
28 | timeClaimKeys.add(EXPIRATION);
29 | timeClaimKeys.add(ISSUED_AT);
30 | }
31 |
32 | Payload(Map map) {
33 | this();
34 | putAll(map);
35 | }
36 |
37 | public String getType() {
38 | return get(TYPE, String.class);
39 | }
40 |
41 | public List getTypes() {
42 | return get(TYPE, List.class);
43 | }
44 |
45 | public String getIss() {
46 | return get(ISSUER, String.class);
47 | }
48 |
49 | public String getSub() {
50 | return get(SUBJECT, String.class);
51 | }
52 |
53 | public String getAud() { return get(AUDIENCE, String.class); }
54 |
55 | public Date getIat() {
56 | return get(ISSUED_AT, Date.class);
57 | }
58 |
59 | public Date getExp() {
60 | return get(EXPIRATION, Date.class);
61 | }
62 |
63 | public Map getClaim() {
64 | return get(CLAIM, Map.class);
65 | }
66 |
67 | public List getCredential() {
68 | return get(CREDENTIAL, List.class);
69 | }
70 |
71 | public String getNonce() {
72 | return get(NONCE, String.class);
73 | }
74 |
75 | public Map getMap() {
76 | return map;
77 | }
78 |
79 | public String getVersion() { return get(VERSION, String.class); }
80 |
81 | public Object put(String name, Object value) {
82 | if (value == null) {
83 | return map.remove(name);
84 | } else {
85 | if (isTimeClaim(name)) {
86 | value = toTimeStamp(value);
87 | }
88 | return map.put(name, value);
89 | }
90 | }
91 |
92 | public void putAll(Map extends String, ?> m) {
93 | if (m == null) {
94 | return;
95 | }
96 | for (String s : m.keySet()) {
97 | put(s, m.get(s));
98 | }
99 | }
100 |
101 | public Object get(Object o) {
102 | return map.get(o);
103 | }
104 |
105 | public T get(String key, Class type) {
106 | Object value = get(key);
107 | if (value == null) {
108 | return null;
109 | }
110 |
111 | if (Date.class.equals(type) && isTimeClaim(key)) {
112 | long seconds = (long) toTimeStamp(value);
113 | value = new Date(seconds * 1000);
114 | }
115 |
116 | return type.cast(value);
117 | }
118 |
119 | public void addTimeClaimKey(String key) {
120 | timeClaimKeys.add(key);
121 | }
122 |
123 | public void addTimeClaimKeys(List keys) {
124 | timeClaimKeys.addAll(keys);
125 | }
126 |
127 | private boolean isTimeClaim(String key) {
128 | return timeClaimKeys.contains(key);
129 | }
130 |
131 | protected static Object toTimeStamp(Object v) {
132 | if (v == null) {
133 | return null;
134 | } else if (v instanceof Number) {
135 | v = ((Number) v).longValue();
136 | } else if (v instanceof String) {
137 | try {
138 | v = Long.parseLong((String) v);
139 | } catch (NumberFormatException ignored) {
140 | }
141 | }
142 | return v;
143 | }
144 |
145 | public static final class Builder {
146 |
147 | // payload
148 | private Map payload;
149 | private List timeClaimKeys;
150 |
151 | public Builder() {
152 | payload = new HashMap<>();
153 | timeClaimKeys = new ArrayList<>();
154 | }
155 |
156 | public Builder(Map payload) {
157 | this.payload = payload;
158 | timeClaimKeys = new ArrayList<>();
159 | }
160 |
161 | public Builder type(List types) {
162 | this.payload.put(Payload.TYPE, types);
163 | return this;
164 | }
165 |
166 | public Builder type(String type) {
167 | this.payload.put(Payload.TYPE, type);
168 | return this;
169 | }
170 |
171 | public Builder iss(String iss) {
172 | this.payload.put(Payload.ISSUER, iss);
173 | return this;
174 | }
175 |
176 | public Builder sub(String sub) {
177 | this.payload.put(Payload.SUBJECT, sub);
178 | return this;
179 | }
180 |
181 | public Builder aud(String aud) {
182 | this.payload.put(Payload.AUDIENCE, aud);
183 | return this;
184 | }
185 |
186 | public Builder iat(Date iat) {
187 | this.payload.put(Payload.ISSUED_AT, dateToSeconds(iat));
188 | return this;
189 | }
190 |
191 | public Builder exp(Date exp) {
192 | this.payload.put(Payload.EXPIRATION, dateToSeconds(exp));
193 | return this;
194 | }
195 |
196 | public Builder claim(Map claim) {
197 | this.payload.put(Payload.CLAIM, claim);
198 | return this;
199 | }
200 |
201 | public Builder credential(List credential) {
202 | this.payload.put(Payload.CREDENTIAL, credential);
203 | return this;
204 | }
205 |
206 | public Builder nonce(String nonce) {
207 | this.payload.put(Payload.NONCE, nonce);
208 | return this;
209 | }
210 |
211 | public Builder jti(String jti) {
212 | this.payload.put(Payload.JTI, jti);
213 | return this;
214 | }
215 |
216 | public Builder version(String version) {
217 | this.payload.put(Payload.VERSION, version);
218 | return this;
219 | }
220 |
221 | public Builder put(String name, Object value) {
222 | if (value == null) {
223 | this.payload.remove(name);
224 | } else {
225 | this.payload.put(name, value);
226 | }
227 | return this;
228 | }
229 |
230 | public Builder addTimeClaimKey(String key) {
231 | this.timeClaimKeys.add(key);
232 | return this;
233 | }
234 |
235 | private long dateToSeconds(Date d) {
236 | if (d == null) throw new IllegalArgumentException("Date must not be null");
237 | return d.getTime() / 1000;
238 | }
239 |
240 | public Payload build() {
241 | Payload payload = new Payload(this.payload);
242 | if (!this.timeClaimKeys.isEmpty()) payload.addTimeClaimKeys(this.timeClaimKeys);
243 | return payload;
244 | }
245 | }
246 |
247 | @Override
248 | public String toString() {
249 | return "Payload{" +
250 | "map=" + map +
251 | '}';
252 | }
253 |
254 | @Override
255 | public boolean equals(Object o) {
256 | if (this == o) return true;
257 | if (!(o instanceof Payload)) return false;
258 | Payload payload = (Payload) o;
259 | return Objects.equals(map, payload.map);
260 | }
261 |
262 | @Override
263 | public int hashCode() {
264 | return Objects.hash(map);
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/score/DidScore.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.score;
2 |
3 |
4 | import foundation.icon.icx.Call;
5 | import foundation.icon.icx.IconService;
6 | import foundation.icon.icx.Transaction;
7 | import foundation.icon.icx.TransactionBuilder;
8 | import foundation.icon.icx.data.Address;
9 | import foundation.icon.icx.transport.jsonrpc.RpcItem;
10 | import foundation.icon.icx.transport.jsonrpc.RpcObject;
11 | import foundation.icon.icx.transport.jsonrpc.RpcValue;
12 |
13 | import java.io.IOException;
14 | import java.math.BigInteger;
15 |
16 | public class DidScore {
17 |
18 | private IconService iconService;
19 | private BigInteger networkId;
20 | private Address scoreAddress;
21 |
22 | public DidScore(IconService iconService, BigInteger networkId, Address scoreAddress) {
23 | this.iconService = iconService;
24 | this.networkId = networkId;
25 | this.scoreAddress = scoreAddress;
26 | }
27 |
28 | public Transaction jwtMethod(Address from, String jwt, String method) {
29 | RpcObject params = new RpcObject.Builder()
30 | .put("jwt", new RpcValue(jwt))
31 | .build();
32 | return buildTransaction(from, method, params);
33 | }
34 |
35 | public String getVersion() throws IOException {
36 | return iconService.call(buildCall(null, "getVersion", null, String.class)).execute();
37 | }
38 |
39 | public Transaction create(Address from, String publicKey) {
40 | RpcObject params = new RpcObject.Builder()
41 | .put("publicKey", new RpcValue(publicKey))
42 | .build();
43 | return buildTransaction(from, "create", params);
44 | }
45 |
46 | public RpcItem getDid(Address from) throws IOException {
47 | return iconService.call(buildCall(from, "getDid", null, RpcItem.class)).execute();
48 | }
49 |
50 | public RpcItem getDidDocument(String did) throws IOException {
51 | RpcObject params = new RpcObject.Builder()
52 | .put("did", new RpcValue(did))
53 | .build();
54 | return iconService.call(buildCall("read", params, RpcItem.class)).execute();
55 | }
56 |
57 | private Transaction buildTransaction(Address from, String method, RpcObject params) {
58 | long timestamp = System.currentTimeMillis() * 1000L;
59 | return TransactionBuilder.newBuilder()
60 | .nid(networkId)
61 | .from(from)
62 | .to(scoreAddress)
63 | .stepLimit(new BigInteger("2000000"))
64 | .timestamp(new BigInteger(Long.toString(timestamp)))
65 | .call(method)
66 | .params(params)
67 | .build();
68 | }
69 |
70 | private Call buildCall(String method, RpcObject params, Class responseType) {
71 | return new Call.Builder()
72 | .to(scoreAddress)
73 | .method(method)
74 | .params(params)
75 | .buildWith(responseType);
76 | }
77 |
78 | private Call buildCall(Address from, String method, RpcObject params, Class responseType) {
79 | return new Call.Builder()
80 | .from(from)
81 | .to(scoreAddress)
82 | .method(method)
83 | .params(params)
84 | .buildWith(responseType);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/src/main/java/foundation/icon/did/score/ScoreParameter.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.score;
2 |
3 | import com.google.gson.JsonObject;
4 | import foundation.icon.did.core.DidKeyHolder;
5 | import foundation.icon.did.core.KeyProvider;
6 | import foundation.icon.did.core.PropertyName;
7 | import foundation.icon.did.document.Converters;
8 | import foundation.icon.did.document.EncodeType;
9 | import foundation.icon.did.document.PublicKeyProperty;
10 | import foundation.icon.did.jwt.Jwt;
11 | import foundation.icon.did.DidService;
12 | import foundation.icon.icx.KeyWallet;
13 |
14 | import java.util.Collections;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 |
18 | /**
19 | * This class is used to create transaction parameters that call a score function that
20 | * can use all the features of the DID document.
21 | */
22 | public class ScoreParameter {
23 |
24 | private ScoreParameter() {
25 | }
26 |
27 | /**
28 | * Create a parameter for transaction that creates the DID Document.
29 | * {@linkplain DidService#create(KeyWallet, String)}
30 | *
31 | * @param keyProvider the KeyProvider object
32 | * @return the json string
33 | */
34 | public static String create(KeyProvider keyProvider, EncodeType encodeType) {
35 | PublicKeyProperty publicKeyProperty = createPublicKeyProperty(keyProvider, encodeType);
36 | return Converters.gson().toJson(publicKeyProperty);
37 | }
38 |
39 | /**
40 | * Create a parameter for transaction that update the DID Document. (add publicKey)
41 | * {@linkplain DidService#addPublicKey(KeyWallet, String)}
42 | *
43 | * @param didKeyHolder the DidKeyHolder object to use for authentication
44 | * @param keyProvider the KeyProvider object to add
45 | * @param encodeType the id of the publicKey to revoke
46 | * @return the Jwt object
47 | */
48 | public static Jwt addKey(DidKeyHolder didKeyHolder, KeyProvider keyProvider, EncodeType encodeType) {
49 | PublicKeyProperty publicKeyProperty = createPublicKeyProperty(keyProvider, encodeType);
50 | JsonObject jsonObject = Converters.gson().toJsonTree(publicKeyProperty).getAsJsonObject();
51 |
52 | Map map = new HashMap<>();
53 | map.put("id", didKeyHolder.getDid());
54 | map.put(PropertyName.KEY_DOCUMENT_PUBLICKEY, jsonObject);
55 |
56 | return new Jwt.Builder()
57 | .alg(didKeyHolder.getType().getName())
58 | .kid(didKeyHolder.getKid())
59 | .put(PropertyName.KEY_TX_UPDATE_METHOD, PropertyName.KEY_TX_UPDATE_METHOD_ADDKEY)
60 | .put(PropertyName.KEY_TX_UPDATE_PARAM, map)
61 | .build();
62 | }
63 |
64 | /**
65 | * Create a parameter for transaction that update the DID Document. (revoke publicKey)
66 | * {@linkplain DidService#revokeKey(KeyWallet, String)}
67 | *
68 | * @param didKeyHolder the DidKeyHolder object to use for authentication
69 | * @param revokeKeyId revoke 할 public key 의 id
70 | * @return the jwt object
71 | */
72 | public static Jwt revokeKey(DidKeyHolder didKeyHolder, String revokeKeyId) {
73 | Map param = new HashMap<>();
74 | param.put(PropertyName.KEY_DOCUMENT_ID, didKeyHolder.getDid());
75 | param.put(PropertyName.KEY_DOCUMENT_PUBLICKEY, revokeKeyId);
76 | return new Jwt.Builder()
77 | .alg(didKeyHolder.getType().getName())
78 | .kid(didKeyHolder.getKid())
79 | .put(PropertyName.KEY_TX_UPDATE_METHOD, PropertyName.KEY_TX_UPDATE_METHOD_REVOKEKEY)
80 | .put(PropertyName.KEY_TX_UPDATE_PARAM, param)
81 | .build();
82 | }
83 |
84 | private static PublicKeyProperty createPublicKeyProperty(KeyProvider keyProvider, EncodeType encodeType) {
85 | return new PublicKeyProperty.Builder()
86 | .id(keyProvider.getKeyId())
87 | .type(Collections.singletonList(keyProvider.getType().getIdentifier()))
88 | .publicKey(keyProvider.getPublicKey())
89 | .encodeType(encodeType)
90 | .build();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/ClaimRequestTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.did.core.Algorithm;
4 | import foundation.icon.did.core.AlgorithmProvider;
5 | import foundation.icon.did.core.DidKeyHolder;
6 | import foundation.icon.did.core.KeyProvider;
7 | import foundation.icon.did.exceptions.AlgorithmException;
8 | import foundation.icon.did.jwt.Header;
9 | import foundation.icon.did.jwt.Jwt;
10 | import foundation.icon.did.jwt.Payload;
11 | import foundation.icon.did.protocol.ClaimRequest;
12 | import org.junit.jupiter.api.Assertions;
13 | import org.junit.jupiter.api.Test;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.util.*;
18 |
19 | @SuppressWarnings("Duplicates")
20 | public class ClaimRequestTest {
21 |
22 | private static Logger logger = LoggerFactory.getLogger(ClaimRequestTest.class);
23 |
24 | @Test
25 | void testCredentialRequest() throws AlgorithmException {
26 |
27 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
28 | KeyProvider keyProvider = algorithm.generateKeyProvider("key");
29 | String ownerDid = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
30 | String issuerDid = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
31 | List claimTypes = Arrays.asList("email");
32 | List claimValues = Arrays.asList("abc@icon.foundation");
33 | String version = "1.0";
34 |
35 | Map claims = new HashMap();
36 | for (int i = 0; i < claimTypes.size(); i++) {
37 | claims.put(claimTypes.get(i), claimValues.get(i));
38 | }
39 |
40 | Date requestDate = new Date();
41 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
42 | .did(ownerDid)
43 | .build();
44 |
45 | ClaimRequest request = new ClaimRequest.Builder(ClaimRequest.Type.CREDENTIAL)
46 | .didKeyHolder(didKeyHolder)
47 | .requestDate(requestDate)
48 | .requestClaims(claims)
49 | .responseId(issuerDid)
50 | .version(version)
51 | .build();
52 |
53 | String signedJwt = didKeyHolder.sign(request.getJwt());
54 | logger.debug("jwt : {}", signedJwt);
55 |
56 | ClaimRequest decodeRequest = ClaimRequest.valueOf(signedJwt);
57 | Map expected = request.getJwt().getPayload().getMap();
58 | Map actual = decodeRequest.getJwt().getPayload().getMap();
59 | Assertions.assertArrayEquals(expected.values().toArray(), actual.values().toArray());
60 | Assertions.assertArrayEquals(expected.keySet().toArray(), actual.keySet().toArray());
61 |
62 | // Header
63 | Header header = request.getJwt().getHeader();
64 | String kid = ownerDid + "#" + didKeyHolder.getKeyId();
65 | Assertions.assertEquals(kid, header.getKid());
66 | Assertions.assertEquals(algorithm.getType().getName(), header.getAlg());
67 |
68 | // Payload
69 | Payload payload = request.getJwt().getPayload();
70 | Assertions.assertEquals(ownerDid, payload.getIss());
71 | List actualTypes = payload.getTypes();
72 | actualTypes.remove(0);
73 | Assertions.assertArrayEquals(claimTypes.toArray(), actualTypes.toArray());
74 | Assertions.assertEquals(claims, decodeRequest.getClaims());
75 | Assertions.assertEquals(requestDate.getTime() / 1000, payload.getIat().getTime() / 1000);
76 |
77 | Jwt.VerifyResult result = decodeRequest.verify(keyProvider.getPublicKey());
78 | Assertions.assertTrue(result.isSuccess());
79 | }
80 |
81 | @Test
82 | void testPresentationRequest() throws AlgorithmException {
83 |
84 | // DID 가 없으면 verify 는 어떻게?
85 | // credentail 과 차이점? subject 가 추가됨
86 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
87 | KeyProvider keyProvider = algorithm.generateKeyProvider("key");
88 | String verifierDid = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
89 | String ownerDid = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
90 | List types = Arrays.asList("passportType", "passportNum");
91 |
92 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
93 | .did(verifierDid)
94 | .build();
95 |
96 | Date requestDate = new Date();
97 | ClaimRequest request = new ClaimRequest.Builder(ClaimRequest.Type.PRESENTATION)
98 | .didKeyHolder(didKeyHolder)
99 | .responseId(ownerDid)
100 | .requestDate(requestDate)
101 | .requestClaimTypes(types)
102 | .build();
103 |
104 | String signedJwt = request.getJwt().sign(didKeyHolder.getPrivateKey());
105 | logger.debug("jwt : {}", signedJwt);
106 |
107 | ClaimRequest decodeRequest = ClaimRequest.valueOf(signedJwt);
108 | Map expected = request.getJwt().getPayload().getMap();
109 | Map actual = decodeRequest.getJwt().getPayload().getMap();
110 | Assertions.assertArrayEquals(expected.values().toArray(), actual.values().toArray());
111 | Assertions.assertArrayEquals(expected.keySet().toArray(), actual.keySet().toArray());
112 |
113 | // Header
114 | Header header = request.getJwt().getHeader();
115 | String kid = verifierDid + "#" + didKeyHolder.getKeyId();
116 | Assertions.assertEquals(kid, header.getKid());
117 | Assertions.assertEquals(algorithm.getType().getName(), header.getAlg());
118 |
119 | // Payload
120 | Payload payload = request.getJwt().getPayload();
121 | Assertions.assertEquals(verifierDid, payload.getIss());
122 | Assertions.assertEquals(ownerDid, payload.getSub());
123 | List actualTypes = payload.getTypes();
124 | actualTypes.remove(0);
125 | Assertions.assertArrayEquals(types.toArray(), actualTypes.toArray());
126 | Assertions.assertEquals(requestDate.getTime() / 1000, payload.getIat().getTime() / 1000);
127 |
128 | Jwt.VerifyResult result = decodeRequest.verify(keyProvider.getPublicKey());
129 | Assertions.assertTrue(result.isSuccess());
130 |
131 | }
132 |
133 | @Test
134 | void testAlgNonePresentationRequest() throws AlgorithmException {
135 |
136 | String ownerDid = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
137 | List types = Arrays.asList("passportType", "passportNum");
138 |
139 | Date requestDate = new Date();
140 | ClaimRequest request = new ClaimRequest.Builder(ClaimRequest.Type.PRESENTATION)
141 | .algorithm(AlgorithmProvider.Type.NONE)
142 | .responseId(ownerDid)
143 | .requestDate(requestDate)
144 | .requestClaimTypes(types)
145 | .build();
146 |
147 | String signedJwt = request.compact();
148 | logger.debug("jwt : {}", signedJwt);
149 |
150 | ClaimRequest decodeRequest = ClaimRequest.valueOf(signedJwt);
151 | Map expected = request.getJwt().getPayload().getMap();
152 | Map actual = decodeRequest.getJwt().getPayload().getMap();
153 | Assertions.assertArrayEquals(expected.values().toArray(), actual.values().toArray());
154 | Assertions.assertArrayEquals(expected.keySet().toArray(), actual.keySet().toArray());
155 |
156 | // Header
157 | Header header = request.getJwt().getHeader();
158 | Assertions.assertEquals(AlgorithmProvider.Type.NONE.getName(), header.getAlg());
159 |
160 | // Payload
161 | Payload payload = request.getJwt().getPayload();
162 | Assertions.assertNull(payload.getIss());
163 | Assertions.assertEquals(ownerDid, payload.getSub());
164 | List actualTypes = payload.getTypes();
165 | actualTypes.remove(0);
166 | Assertions.assertArrayEquals(types.toArray(), actualTypes.toArray());
167 | Assertions.assertEquals(requestDate.getTime() / 1000, payload.getIat().getTime() / 1000);
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/CredentialTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.did.core.Algorithm;
4 | import foundation.icon.did.core.AlgorithmProvider;
5 | import foundation.icon.did.document.EncodeType;
6 | import foundation.icon.did.jwt.Jwt;
7 | import org.junit.jupiter.api.Assertions;
8 | import org.junit.jupiter.api.Test;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 | import java.security.PrivateKey;
13 | import java.util.Arrays;
14 | import java.util.stream.Collectors;
15 |
16 | public class CredentialTest {
17 |
18 | private static Logger logger = LoggerFactory.getLogger(CredentialTest.class);
19 |
20 | @Test
21 | void testBuildJwt() throws Exception {
22 |
23 | String keyId = TestKeys.ISSUER_KEY_ID;
24 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
25 | Algorithm algorithm = AlgorithmProvider.create(type);
26 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
27 |
28 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
29 | Credential credential = new Credential.Builder()
30 | .algorithm(type.getName())
31 | .keyId(keyId)
32 | .did(did)
33 | .build();
34 |
35 | Assertions.assertEquals(did, credential.getIssuerDid().getDid());
36 |
37 | String owner = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
38 |
39 | credential.setTargetDid(owner);
40 | credential.addClaim("email", "aaa@icon.foundation");
41 | String jwt = credential.buildJwt().sign(priKey);
42 | logger.debug("jwt : {}", jwt);
43 | }
44 |
45 | @Test
46 | void testDecode() throws Exception {
47 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
48 | Algorithm algorithm = AlgorithmProvider.create(type);
49 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
50 | String encodedJwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaXNzdWVyIn0=.eyJjbGFpbSI6eyJFbWFpbCI6ImFhYUBpY29uLmZvdW5kYXRpb24ifSwiZXhwIjoxNTQ3ODIwMzg2LCJpYXQiOjE1NDc3MzM5ODYsImlzcyI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJub25jZSI6IjAzMDcxZjJkLThiZTAtNDAxNS04Y2I4LTg4YTI3M2FiZWY2NiIsInN1YiI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJ0eXBlIjpbIkNSRURFTlRJQUwiLCJFbWFpbCJdfQ==";
51 | Jwt decode = Jwt.decode(encodedJwt);
52 | Credential credential = Credential.valueOf(decode);
53 | String jwt = credential.buildJwt(decode.getPayload().getIat(), decode.getPayload().getExp()).sign(priKey);
54 | String actualJwt = String.join(".", Arrays.asList(jwt.split("\\.")).stream().limit(2).collect(Collectors.toList()));
55 | Assertions.assertEquals(encodedJwt, actualJwt);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/DIDBuildJwtTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.did.core.*;
4 | import foundation.icon.did.document.Converters;
5 | import foundation.icon.did.document.EncodeType;
6 | import foundation.icon.did.document.PublicKeyProperty;
7 | import foundation.icon.did.jwt.Jwt;
8 | import foundation.icon.did.score.ScoreParameter;
9 | import org.junit.jupiter.api.Assertions;
10 | import org.junit.jupiter.api.Test;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.security.PrivateKey;
15 | import java.security.PublicKey;
16 |
17 | import static foundation.icon.did.TestKeys.TEMP_DID;
18 |
19 | public class DIDBuildJwtTest {
20 |
21 | private static Logger logger = LoggerFactory.getLogger(DIDBuildJwtTest.class);
22 |
23 | @Test
24 | void testBuildCreateJwt() throws Exception {
25 | String keyId = "key1";
26 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
27 | Algorithm algorithm = AlgorithmProvider.create(type);
28 | PublicKey publicKey = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_ES256));
29 | PrivateKey privateKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
30 | KeyProvider keyProvider = new KeyProvider.Builder()
31 | .keyId(keyId)
32 | .publicKey(publicKey)
33 | .privateKey(privateKey)
34 | .type(type)
35 | .build();
36 |
37 |
38 | String json = ScoreParameter.create(keyProvider, EncodeType.HEX);
39 | logger.debug("json: {}", json);
40 | PublicKeyProperty publicKeyProperty = Converters.gson().fromJson(json, PublicKeyProperty.class);
41 | Assertions.assertEquals(keyId, publicKeyProperty.getId());
42 | Assertions.assertEquals(type.getIdentifier(), publicKeyProperty.getType().get(0));
43 | Assertions.assertArrayEquals(algorithm.publicKeyToByte(publicKey), algorithm.publicKeyToByte(publicKeyProperty.getPublicKey()));
44 | }
45 |
46 | @Test
47 | void testBuildAddKeyJwt() throws Exception {
48 |
49 | // authentication public / private key
50 | String authKeyId = "key1";
51 | AlgorithmProvider.Type authType = AlgorithmProvider.Type.ES256;
52 | Algorithm algorithm = AlgorithmProvider.create(authType);
53 | PrivateKey authPrivateKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
54 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder()
55 | .did(TEMP_DID)
56 | .keyId(authKeyId)
57 | .privateKey(authPrivateKey)
58 | .type(authType)
59 | .build();
60 |
61 | // add public / private key
62 | String key2 = "key2";
63 | AlgorithmProvider.Type type2 = AlgorithmProvider.Type.RS256;
64 | algorithm = AlgorithmProvider.create(type2);
65 | PublicKey publicKey = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_RS256));
66 | PrivateKey privateKey2 = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_RS256));
67 | KeyProvider keyProvider2 = new KeyProvider.Builder()
68 | .keyId(key2)
69 | .publicKey(publicKey)
70 | .privateKey(privateKey2)
71 | .type(type2)
72 | .build();
73 |
74 |
75 | String json = ScoreParameter.create(keyProvider2, EncodeType.BASE64);
76 | logger.debug("json: {}", json);
77 |
78 | Jwt addJwt = ScoreParameter.addKey(didKeyHolder, keyProvider2, EncodeType.BASE64);
79 | logger.debug("encodedJwt: {}", didKeyHolder.sign(addJwt));
80 | }
81 |
82 | @Test
83 | void testBuildRevokeKeyJwt() throws Exception {
84 | String authKeyId = "key1";
85 | AlgorithmProvider.Type authType = AlgorithmProvider.Type.ES256;
86 | Algorithm algorithm = AlgorithmProvider.create(authType);
87 | PrivateKey authPrivateKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
88 |
89 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder()
90 | .did(TEMP_DID)
91 | .keyId(authKeyId)
92 | .privateKey(authPrivateKey)
93 | .type(authType)
94 | .build();
95 |
96 | Jwt jwt = ScoreParameter.revokeKey(didKeyHolder, "key2");
97 | logger.debug("encodedJwt: {}", didKeyHolder.sign(jwt));
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/DidJwtServiceTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.*;
5 | import foundation.icon.did.document.Document;
6 | import foundation.icon.did.document.EncodeType;
7 | import foundation.icon.did.document.PublicKeyProperty;
8 | import foundation.icon.did.exceptions.AlgorithmException;
9 | import foundation.icon.did.exceptions.KeyPairException;
10 | import foundation.icon.did.exceptions.KeystoreException;
11 | import foundation.icon.did.jwt.Jwt;
12 | import foundation.icon.did.score.ScoreParameter;
13 | import foundation.icon.icx.IconService;
14 | import foundation.icon.icx.KeyWallet;
15 | import foundation.icon.icx.data.Address;
16 | import foundation.icon.icx.data.Bytes;
17 | import org.junit.jupiter.api.*;
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.math.BigInteger;
24 | import java.security.PrivateKey;
25 | import java.security.PublicKey;
26 |
27 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
28 | public class DidJwtServiceTest {
29 |
30 | private static Logger logger = LoggerFactory.getLogger(DidJwtServiceTest.class);
31 | private final String PASSWORD = "P@ssw0rd";
32 | private final String FILE_NAME = "temp.json";
33 | private DidService didService;
34 |
35 | @BeforeEach
36 | public void setUp() throws Exception {
37 | BigInteger networkId = new BigInteger("3");
38 | IconService iconService = IconServiceFactory.createLocal();
39 | Address scoreAddress = new Address("cx26484cf9cb42b6eebbf537fbfe6b7df3f86c5079");
40 |
41 | // cx5681b1427cb3d7ca37c66dffa74e90bfb268c43d
42 | // BigInteger networkId = new BigInteger("2");
43 | // IconService iconService = IconServiceFactory.createDev();
44 | // Address scoreAddress = new Address("cx9a96c0dcf0567635309809d391908c32fcca5310");
45 |
46 | didService = new DidService(iconService, networkId, scoreAddress);
47 | }
48 |
49 | @Test
50 | void testGetVersion() throws IOException {
51 | Assertions.assertDoesNotThrow(() -> {
52 | String version = didService.getVersion();
53 | logger.debug("version:{}", version);
54 | });
55 | }
56 |
57 | @Test
58 | @Order(2)
59 | void testCreate() throws AlgorithmException, IOException, KeystoreException {
60 | KeyWallet wallet = KeyWallet.load(new Bytes(TestKeys.ICON_WALLET_PRIVATE_KEY));
61 | String keyId = "ES256K-key";
62 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256K;
63 | Algorithm algorithm = AlgorithmProvider.create(type);
64 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
65 | String json = ScoreParameter.create(keyProvider, EncodeType.BASE64);
66 | Document doc = didService.create(wallet, json);
67 |
68 | logger.debug("json - {}", json);
69 | logger.debug("DID Document - {}", doc);
70 | logger.debug("DID Document json - {}", doc.toJson());
71 |
72 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
73 | .did(doc.getId())
74 | .build();
75 |
76 | Assertions.assertEquals(keyId, doc.getPublicKeyProperty(keyId).getId());
77 | Assertions.assertArrayEquals(algorithm.publicKeyToByte(keyProvider.getPublicKey()),
78 | algorithm.publicKeyToByte(doc.getPublicKeyProperty(keyId).getPublicKey()));
79 |
80 | logger.debug("file path : {}", new File(FILE_NAME).getPath());
81 | Keystore.storeDidKeyHolder(PASSWORD, didKeyHolder, FILE_NAME);
82 | }
83 |
84 | @Test
85 | @Order(4)
86 | void testUpdate() throws Exception {
87 | KeyWallet wallet = KeyWallet.load(new Bytes(TestKeys.ICON_WALLET_PRIVATE_KEY));
88 | DidKeyHolder keyHolder = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
89 | logger.debug("file path : {}", new File(FILE_NAME).getPath());
90 | logger.debug("didKeyHolder : {}", keyHolder);
91 |
92 | String key2 = "newKey";
93 | AlgorithmProvider.Type type2 = AlgorithmProvider.Type.ES256K;
94 | Algorithm algorithm = AlgorithmProvider.create(type2);
95 | KeyProvider keyProvider2 = algorithm.generateKeyProvider(key2);
96 |
97 | Jwt addJwt = ScoreParameter.addKey(keyHolder, keyProvider2, EncodeType.BASE64);
98 | String signedJwt = keyHolder.sign(addJwt);
99 | Document doc = didService.addPublicKey(wallet, signedJwt);
100 |
101 | logger.debug("signedJwt - {}", signedJwt);
102 | logger.debug("DID Document - {}", doc);
103 | logger.debug("DID Document json - {}", doc.toJson());
104 |
105 | Assertions.assertEquals(key2, doc.getPublicKeyProperty(key2).getId());
106 | Assertions.assertArrayEquals(algorithm.publicKeyToByte(keyProvider2.getPublicKey()),
107 | algorithm.publicKeyToByte(doc.getPublicKeyProperty(key2).getPublicKey()));
108 | }
109 |
110 | @Test
111 | @Order(5)
112 | void testRevoke() throws Exception {
113 | KeyWallet wallet = KeyWallet.load(new Bytes(TestKeys.ICON_WALLET_PRIVATE_KEY));
114 |
115 | DidKeyHolder keyHolder = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
116 | logger.debug("file path : {}", new File(FILE_NAME).getPath());
117 | logger.debug("didKeyHolder : {}", keyHolder);
118 |
119 | String revokeKeyId = "newKey";
120 | Jwt revokeJwt = ScoreParameter.revokeKey(keyHolder, revokeKeyId);
121 | String signedJwt = keyHolder.sign(revokeJwt);
122 | Document doc = didService.revokeKey(wallet, signedJwt);
123 |
124 | logger.debug("signedJwt - {}", signedJwt);
125 | logger.debug("DID Document - {}", doc);
126 | logger.debug("DID Document json - {}", doc.toJson());
127 |
128 | Assertions.assertTrue(doc.getPublicKeyProperty(revokeKeyId).isRevoked());
129 | }
130 |
131 | @Test
132 | @Order(3)
133 | void testReadDocument() throws Exception {
134 | DidKeyHolder keyHolder = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
135 |
136 | Document doc = didService.readDocument(keyHolder.getDid());
137 |
138 | PublicKeyProperty didPublicKey = doc.getPublicKeyProperty(keyHolder.getKeyId());
139 | Assertions.assertNotNull(didPublicKey);
140 | Assertions.assertEquals(keyHolder.getKeyId(), didPublicKey.getId());
141 |
142 | logger.debug("DID Document json - {}", doc);
143 | logger.debug("DID Document json - {}", doc.toJson());
144 | }
145 |
146 | @Test
147 | void testCreateDocumentWalletPublicKey() throws KeyPairException, IOException, AlgorithmException {
148 | KeyWallet wallet = KeyWallet.load(new Bytes(TestKeys.ICON_WALLET_PRIVATE_KEY));
149 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256K;
150 | Algorithm algorithm = AlgorithmProvider.create(type);
151 | String keyId = "IconWallet";
152 |
153 | PublicKey publicKey = algorithm.byteToPublicKey(wallet.getPublicKey().toByteArray());
154 | PrivateKey privateKey = algorithm.byteToPrivateKey(wallet.getPrivateKey().toByteArray());
155 |
156 | KeyProvider keyProvider = new KeyProvider.Builder()
157 | .keyId(keyId)
158 | .publicKey(publicKey)
159 | .privateKey(privateKey)
160 | .type(type)
161 | .build();
162 |
163 | String json = ScoreParameter.create(keyProvider, EncodeType.BASE64);
164 | logger.debug("DID Json - {}", json);
165 | Document doc = didService.create(wallet, json);
166 | logger.debug("DID Document - {}", doc);
167 | logger.debug("DID Document json - {}", doc.toJson());
168 |
169 | PublicKeyProperty didPublicKey = doc.getPublicKeyProperty(keyId);
170 | Assertions.assertEquals(keyId, didPublicKey.getId());
171 | Assertions.assertArrayEquals(algorithm.publicKeyToByte(keyProvider.getPublicKey()),
172 | algorithm.publicKeyToByte(doc.getPublicKeyProperty(keyId).getPublicKey()));
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/IconServiceFactory.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.icx.IconService;
4 | import foundation.icon.icx.transport.http.HttpProvider;
5 | import okhttp3.OkHttpClient;
6 | import okhttp3.logging.HttpLoggingInterceptor;
7 |
8 | import java.util.concurrent.TimeUnit;
9 |
10 | /**
11 | * Test 용으로 사용
12 | */
13 | public class IconServiceFactory {
14 |
15 | private static boolean DEBUG = false;
16 | private static String LOCAL_URL = "http://127.0.0.1:9000/api/v3";
17 | private static String DEV_URL = "https://test-ctz.solidwallet.io/api/v3";
18 |
19 | private IconServiceFactory() {
20 | }
21 |
22 | public static IconService createLocal() {
23 | return create(LOCAL_URL);
24 | }
25 |
26 | public static IconService createDev() {
27 | return create(DEV_URL);
28 | }
29 |
30 | public static IconService create(String url) {
31 | return new IconService(createHttpProvider(url, DEBUG));
32 | }
33 |
34 | private static HttpProvider createHttpProvider(String url, boolean debug) {
35 | if (!debug) {
36 | return new HttpProvider(url);
37 | } else {
38 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
39 | logging.setLevel(HttpLoggingInterceptor.Level.BODY);
40 | OkHttpClient httpClient = new OkHttpClient.Builder()
41 | .addInterceptor(logging)
42 | .readTimeout(100L, TimeUnit.SECONDS)
43 | .build();
44 | return new HttpProvider(httpClient, url);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/IssuerDidTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.*;
5 | import foundation.icon.did.document.EncodeType;
6 | import foundation.icon.did.jwt.IssuerDid;
7 | import foundation.icon.did.jwt.Jwt;
8 | import org.junit.jupiter.api.Assertions;
9 | import org.junit.jupiter.api.Test;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import java.security.PrivateKey;
14 | import java.security.PublicKey;
15 | import java.util.Date;
16 |
17 | class IssuerDidTest {
18 |
19 | private static Logger logger = LoggerFactory.getLogger(IssuerDidTest.class);
20 |
21 | @Test
22 | void testCreate() {
23 | String keyId = "key1";
24 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
25 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
26 | IssuerDid issuerDid = new IssuerDid.Builder()
27 | .did(did)
28 | .algorithm(type.getName())
29 | .keyId(keyId)
30 | .build();
31 |
32 | logger.debug("issuerDid: {}", issuerDid);
33 |
34 | Assertions.assertEquals(keyId, issuerDid.getKeyId());
35 | Assertions.assertEquals(did, issuerDid.getDid());
36 | Assertions.assertEquals(type.getName(), issuerDid.getAlgorithm());
37 | }
38 |
39 | @Test
40 | void testParse() throws Exception {
41 | String keyId = "key1";
42 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
43 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
44 | Algorithm algorithm = AlgorithmProvider.create(type);
45 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
46 |
47 | IssuerDid issuerDid = new IssuerDid.Builder()
48 | .did(did)
49 | .algorithm(type.getName())
50 | .keyId(keyId)
51 | .build();
52 |
53 | logger.debug("issuerDid: {}", issuerDid);
54 |
55 | String jwt = issuerDid.buildJwt().sign(priKey);
56 |
57 | logger.debug("buildJwt: {}", jwt);
58 |
59 | IssuerDid parseIssuerDid = IssuerDid.valueOf(jwt);
60 |
61 | logger.debug("parse IssuerDid: {}", parseIssuerDid);
62 |
63 | Assertions.assertEquals(keyId, parseIssuerDid.getKeyId());
64 | Assertions.assertEquals(did, parseIssuerDid.getDid());
65 | Assertions.assertEquals(type.getName(), parseIssuerDid.getAlgorithm());
66 | }
67 |
68 | @Test
69 | void testES256Compact() throws Exception {
70 | String keyId = "key1";
71 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
72 | Algorithm algorithm = AlgorithmProvider.create(type);
73 | PublicKey pubKey = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_ES256));
74 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
75 |
76 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
77 | IssuerDid issuerDid = new IssuerDid.Builder()
78 | .did(did)
79 | .keyId(keyId)
80 | .algorithm(type.getName())
81 | .build();
82 |
83 |
84 | long issuedTimestamp = 1545208842000L;
85 | Date issued = new Date(issuedTimestamp);
86 | long duration = issuerDid.getDuration() * 1000L; // to milliseconds
87 | Date expiration = new Date(issuedTimestamp + duration);
88 |
89 | String jwt = issuerDid.buildJwt(issued, expiration).sign(priKey);
90 | logger.debug("buildJwt: {}", jwt);
91 |
92 | Jwt didJwt = Jwt.decode(jwt);
93 |
94 | Assertions.assertFalse(didJwt.verify(pubKey).isSuccess());
95 | Assertions.assertEquals(PropertyName.ALGO_KEY_ECDSA, didJwt.getHeader().getAlg());
96 | Assertions.assertEquals(did + "#" + keyId, didJwt.getHeader().getKid());
97 | Assertions.assertEquals(issued, didJwt.getPayload().getIat());
98 | Assertions.assertEquals(expiration, didJwt.getPayload().getExp());
99 |
100 | }
101 |
102 | @Test
103 | void testRS256Compact() throws Exception {
104 | String keyId = "key1";
105 | AlgorithmProvider.Type type = AlgorithmProvider.Type.RS256;
106 | Algorithm algorithm = AlgorithmProvider.create(type);
107 | PublicKey publicKey = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_RS256));
108 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_RS256));
109 |
110 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
111 | IssuerDid issuerDid = new IssuerDid.Builder()
112 | .did(did)
113 | .keyId(keyId)
114 | .algorithm(type.getName())
115 | .build();
116 |
117 | long issuedTimestamp = 1545208842000L;
118 | Date issued = new Date(issuedTimestamp);
119 | long duration = issuerDid.getDuration() * 1000L; // to milliseconds
120 | Date expiration = new Date(issuedTimestamp + duration);
121 |
122 | String jwt = issuerDid.buildJwt(issued, expiration).sign(priKey);
123 | logger.debug("buildJwt: {}", jwt);
124 |
125 | Jwt didJwt = Jwt.decode(jwt);
126 | Assertions.assertFalse(didJwt.verify(publicKey).isSuccess());
127 | Assertions.assertEquals(PropertyName.ALGO_KEY_RSA, didJwt.getHeader().getAlg());
128 | Assertions.assertEquals(did + "#" + keyId, didJwt.getHeader().getKid());
129 | Assertions.assertEquals(issued, didJwt.getPayload().getIat());
130 | Assertions.assertEquals(expiration, didJwt.getPayload().getExp());
131 |
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/JJwtTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.Algorithm;
5 | import foundation.icon.did.core.AlgorithmProvider;
6 | import foundation.icon.did.jwt.IssuerDid;
7 | import io.jsonwebtoken.*;
8 | import io.jsonwebtoken.security.SignatureException;
9 | import org.bouncycastle.util.encoders.Hex;
10 | import org.junit.jupiter.api.Test;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.security.PrivateKey;
15 | import java.security.PublicKey;
16 | import java.util.Date;
17 |
18 | public class JJwtTest {
19 |
20 | private static Logger logger = LoggerFactory.getLogger(JJwtTest.class);
21 |
22 | @Test
23 | void testCreate() {
24 | String keyId = "key1";
25 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
26 | String kid = did + "#" + keyId;
27 |
28 | long duration = 5 * 60;
29 | Date iat = new Date();
30 | Date exp = new Date(iat.getTime() + duration * 1000L);
31 | String encodedJwt = Jwts.builder()
32 | .setHeaderParam("alg", "ES256")
33 | .setHeaderParam("kid", kid)
34 | .setIssuer(did)
35 | .setIssuedAt(iat)
36 | .setExpiration(exp)
37 | .compact();
38 |
39 | logger.debug("encodedJwt: {}", encodedJwt);
40 | try {
41 | Jwt jwt = Jwts.parser()
42 | .parseClaimsJwt(encodedJwt);
43 | logger.debug("decode jwt: {}", jwt);
44 |
45 | } catch (ExpiredJwtException e) {
46 | e.printStackTrace();
47 | } catch (MalformedJwtException e) {
48 | e.printStackTrace();
49 | } catch (SignatureException e) {
50 | e.printStackTrace();
51 | } catch (IllegalArgumentException e) {
52 | e.printStackTrace();
53 | }
54 | }
55 |
56 | @Test
57 | void testExpiredJwt() throws Exception {
58 | String keyId = "key1";
59 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
60 | PublicKey pubKey = algorithm.byteToPublicKey(Hex.decode("3059301306072a8648ce3d020106082a8648ce3d030107034200049548b1aedbb7b812ef2412c7922cde2f9b358939877410cce4a6777ec1b651f17b5a169be5d175d5f801069653a429ccf42c7e6ff9223ffee957dbf8ff5de917"));
61 | PrivateKey priKey = algorithm.byteToPrivateKey(Hex.decode("308193020100301306072a8648ce3d020106082a8648ce3d03010704793077020101042059e7f78342999fc71dc12e63e6747d0a1c9059d3cf1140a2af9a1b7eb4e3e0dda00a06082a8648ce3d030107a144034200049548b1aedbb7b812ef2412c7922cde2f9b358939877410cce4a6777ec1b651f17b5a169be5d175d5f801069653a429ccf42c7e6ff9223ffee957dbf8ff5de917"));
62 |
63 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
64 | IssuerDid issuerDid = new IssuerDid.Builder()
65 | .did(did)
66 | .algorithm(algorithm.getType().getName())
67 | .keyId(keyId)
68 | .build();
69 |
70 |
71 | // epoch timestamp 를 사용해야함
72 | Date issued = new Date(1547627598000L);
73 | Date expiration = new Date(1547627598000L);
74 |
75 | String encodedJwt = issuerDid.buildJwt(issued, expiration).sign(priKey);
76 | logger.debug("encodedJwt: {}", encodedJwt);
77 |
78 | try {
79 | io.jsonwebtoken.Jws jwtparser = Jwts.parser()
80 | .setSigningKey(pubKey)
81 | .parseClaimsJws(encodedJwt);
82 | logger.debug("jwt parser:{}", jwtparser);
83 | } catch (ExpiredJwtException e) {
84 | e.printStackTrace();
85 | } catch (MalformedJwtException e) {
86 | e.printStackTrace();
87 | } catch (SignatureException e) {
88 | e.printStackTrace();
89 | } catch (IllegalArgumentException e) {
90 | e.printStackTrace();
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/PemUtilsTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.Algorithm;
5 | import foundation.icon.did.core.AlgorithmProvider;
6 | import foundation.icon.did.core.KeyProvider;
7 | import foundation.icon.did.document.EncodeType;
8 | import org.bouncycastle.util.io.pem.PemObject;
9 | import org.bouncycastle.util.io.pem.PemReader;
10 | import org.bouncycastle.util.io.pem.PemWriter;
11 | import org.junit.jupiter.api.Assertions;
12 | import org.junit.jupiter.api.Test;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | import java.io.*;
17 | import java.security.*;
18 | import java.security.spec.EncodedKeySpec;
19 | import java.security.spec.InvalidKeySpecException;
20 | import java.security.spec.PKCS8EncodedKeySpec;
21 | import java.security.spec.X509EncodedKeySpec;
22 |
23 | public class PemUtilsTest {
24 |
25 | private final static Logger logger = LoggerFactory.getLogger(PemUtilsTest.class);
26 |
27 | @Test
28 | void testWriteRS256PemFile() throws Exception {
29 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.RS256);
30 | PublicKey key = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_RS256));
31 |
32 | PemObject pemObject = new PemObject("PUBLIC KEY", key.getEncoded());
33 | File file = new File("test-public.pem");
34 | FileOutputStream fileOutputStream = new FileOutputStream(file);
35 | PemWriter pemWriter = new PemWriter(new OutputStreamWriter(fileOutputStream));
36 | pemWriter.writeObject(pemObject);
37 | pemWriter.close();
38 |
39 | byte[] b = parsePEMFile(file);
40 | PublicKey p = getPublicKey(b, "RSA");
41 | Assertions.assertArrayEquals(key.getEncoded(), p.getEncoded());
42 | }
43 |
44 | @Test
45 | void testWriteES256PemFile() throws Exception {
46 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
47 | PublicKey key = algorithm.byteToPublicKey(EncodeType.HEX.decode(TestKeys.PUBLIC_KEY_ES256));
48 |
49 | PemObject pemObject = new PemObject("PUBLIC KEY", key.getEncoded());
50 | File file = new File("test-es-public.pem");
51 | FileOutputStream fileOutputStream = new FileOutputStream(file);
52 | PemWriter pemWriter = new PemWriter(new OutputStreamWriter(fileOutputStream));
53 | pemWriter.writeObject(pemObject);
54 | pemWriter.close();
55 |
56 | byte[] b = parsePEMFile(file);
57 | PublicKey p = getPublicKey(b, "EC");
58 | Assertions.assertArrayEquals(key.getEncoded(), p.getEncoded());
59 | }
60 |
61 | @Test
62 | void testWriteNewES256PemFile() throws Exception {
63 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
64 | Algorithm algorithm = AlgorithmProvider.create(type);
65 | KeyPair keyPair = algorithm.generateKeyPair();
66 | KeyProvider keyProvider = new KeyProvider.Builder()
67 | .keyId("new")
68 | .publicKey(keyPair.getPublic())
69 | .type(type)
70 | .build();
71 | PublicKey key = keyProvider.getPublicKey();
72 | PemObject pemObject = new PemObject("PUBLIC KEY", key.getEncoded());
73 | File file = new File("test-es-public.pem");
74 | FileOutputStream fileOutputStream = new FileOutputStream(file);
75 | PemWriter pemWriter = new PemWriter(new OutputStreamWriter(fileOutputStream));
76 | pemWriter.writeObject(pemObject);
77 | pemWriter.close();
78 |
79 | byte[] b = parsePEMFile(file);
80 | PublicKey p = getPublicKey(b, "EC");
81 | Assertions.assertArrayEquals(key.getEncoded(), p.getEncoded());
82 | }
83 |
84 | private static byte[] parsePEMFile(File pemFile) throws IOException {
85 | if (!pemFile.isFile() || !pemFile.exists()) {
86 | throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));
87 | }
88 | PemReader reader = new PemReader(new FileReader(pemFile));
89 | PemObject pemObject = reader.readPemObject();
90 | byte[] content = pemObject.getContent();
91 | reader.close();
92 | return content;
93 | }
94 |
95 | private static PublicKey getPublicKey(byte[] keyBytes, String algorithm) {
96 | PublicKey publicKey = null;
97 | try {
98 | KeyFactory kf = KeyFactory.getInstance(algorithm);
99 | EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
100 | publicKey = kf.generatePublic(keySpec);
101 | } catch (NoSuchAlgorithmException e) {
102 | System.out.println("Could not reconstruct the public key, the given algorithm could not be found.");
103 | } catch (InvalidKeySpecException e) {
104 | System.out.println("Could not reconstruct the public key");
105 | }
106 |
107 | return publicKey;
108 | }
109 |
110 | private static PrivateKey getPrivateKey(byte[] keyBytes, String algorithm) {
111 | PrivateKey privateKey = null;
112 | try {
113 | KeyFactory kf = KeyFactory.getInstance(algorithm);
114 | EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
115 | privateKey = kf.generatePrivate(keySpec);
116 | } catch (NoSuchAlgorithmException e) {
117 | System.out.println("Could not reconstruct the private key, the given algorithm could not be found.");
118 | } catch (InvalidKeySpecException e) {
119 | System.out.println("Could not reconstruct the private key");
120 | }
121 |
122 | return privateKey;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/PresentationTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.did.core.Algorithm;
4 | import foundation.icon.did.core.AlgorithmProvider;
5 | import foundation.icon.did.core.DidKeyHolder;
6 | import foundation.icon.did.document.EncodeType;
7 | import foundation.icon.did.jwt.IssuerDid;
8 | import foundation.icon.did.jwt.Jwt;
9 | import org.bouncycastle.util.encoders.Hex;
10 | import org.junit.jupiter.api.Assertions;
11 | import org.junit.jupiter.api.Test;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 |
15 | import java.security.PrivateKey;
16 | import java.security.PublicKey;
17 | import java.util.Arrays;
18 | import java.util.Date;
19 | import java.util.List;
20 | import java.util.Map;
21 | import java.util.stream.Collectors;
22 |
23 | public class PresentationTest {
24 |
25 | private static Logger logger = LoggerFactory.getLogger(PresentationTest.class);
26 |
27 | @Test
28 | void testBuildJwt() throws Exception {
29 |
30 | String keyId = TestKeys.HOLDER_KEY_ID;
31 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256;
32 | Algorithm algorithm = AlgorithmProvider.create(type);
33 | PrivateKey priKey = algorithm.byteToPrivateKey(EncodeType.HEX.decode(TestKeys.PRIVATE_KEY_ES256));
34 |
35 | String rawCredential = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaXNzdWVyIn0.eyJjbGFpbSI6eyJFbWFpbCI6ImFhYUBpY29uLmZvdW5kYXRpb24ifSwiZXhwIjoxNTQ3ODIwMzg2LCJpYXQiOjE1NDc3MzM5ODYsImlzcyI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJub25jZSI6IjAzMDcxZjJkLThiZTAtNDAxNS04Y2I4LTg4YTI3M2FiZWY2NiIsInN1YiI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJ0eXBlIjpbIkVtYWlsIl19";
36 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
37 | String version = "1.0";
38 | DidKeyHolder keyHolder = new DidKeyHolder.Builder()
39 | .did(did)
40 | .keyId(keyId)
41 | .type(type)
42 | .privateKey(priKey)
43 | .build();
44 |
45 | Presentation presentation = new Presentation.Builder()
46 | .didKeyHolder(keyHolder)
47 | .build();
48 | presentation.addCredential(rawCredential);
49 | presentation.setNonce("6a41b8a4-d18d-4e31-b5f8-f39b15db5827");
50 | presentation.setVersion(version);
51 |
52 | long issuedTimestamp = 1545208842000L;
53 | Date issued = new Date(issuedTimestamp);
54 | long duration = presentation.getIssuerDid().getDuration() * 1000L; // to milliseconds
55 | Date expiration = new Date(issuedTimestamp + duration);
56 |
57 | Jwt didJwt = presentation.buildJwt(issued, expiration);
58 |
59 | String jwt = keyHolder.sign(didJwt);
60 | String expectedJwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaG9sZGVyIn0=.eyJjcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOaUlzSW10cFpDSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2phWE56ZFdWeUluMC5leUpqYkdGcGJTSTZleUpGYldGcGJDSTZJbUZoWVVCcFkyOXVMbVp2ZFc1a1lYUnBiMjRpZlN3aVpYaHdJam94TlRRM09ESXdNemcyTENKcFlYUWlPakUxTkRjM016TTVPRFlzSW1semN5STZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0p1YjI1alpTSTZJakF6TURjeFpqSmtMVGhpWlRBdE5EQXhOUzA0WTJJNExUZzRZVEkzTTJGaVpXWTJOaUlzSW5OMVlpSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0owZVhCbElqcGJJa1Z0WVdsc0lsMTkiXSwiZXhwIjoxNTQ1MjA5MTQyLCJpYXQiOjE1NDUyMDg4NDIsImlzcyI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJub25jZSI6IjZhNDFiOGE0LWQxOGQtNGUzMS1iNWY4LWYzOWIxNWRiNTgyNyIsInR5cGUiOlsiUFJFU0VOVEFUSU9OIiwiRW1haWwiXX0=";
61 | String actualJwt = String.join(".", Arrays.asList(jwt.split("\\.")).stream().limit(2).collect(Collectors.toList()));
62 | Assertions.assertEquals(expectedJwt, actualJwt);
63 | }
64 |
65 | @Test
66 | void testParse() throws Exception {
67 | String jwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaG9sZGVyIn0.eyJjbGFpbXMiOlsiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHBwWTI5dU9qQXdNREE1TmpGaU5tTmtOalF5TlRObVlqSTRZemxpTUdRelpESXlOR0psTldZNVlqRTRaRFE1WmpBeFpHRXpPVEJtTURnamFYTnpkV1Z5SW4wLmV5SmpiR0ZwYlNJNmV5SkZiV0ZwYkNJNkltRmhZVUJwWTI5dUxtWnZkVzVrWVhScGIyNGlmU3dpWlhod0lqb3hOVFEzT0RJd016ZzJMQ0pwWVhRaU9qRTFORGMzTXpNNU9EWXNJbWx6Y3lJNkltUnBaRHBwWTI5dU9qQXdNREE1TmpGaU5tTmtOalF5TlRObVlqSTRZemxpTUdRelpESXlOR0psTldZNVlqRTRaRFE1WmpBeFpHRXpPVEJtTURnaUxDSnViMjVqWlNJNklqQXpNRGN4WmpKa0xUaGlaVEF0TkRBeE5TMDRZMkk0TFRnNFlUSTNNMkZpWldZMk5pSXNJbk4xWWlJNkltUnBaRHBwWTI5dU9qQXdNREE1TmpGaU5tTmtOalF5TlRObVlqSTRZemxpTUdRelpESXlOR0psTldZNVlqRTRaRFE1WmpBeFpHRXpPVEJtTURnaUxDSjBlWEJsSWpwYklrVnRZV2xzSWwxOSJdLCJleHAiOjE1NDUyMDkxNDIsImlhdCI6MTU0NTIwODg0MiwiaXNzIjoiZGlkOmljb246MDAwMDk2MWI2Y2Q2NDI1M2ZiMjhjOWIwZDNkMjI0YmU1ZjliMThkNDlmMDFkYTM5MGYwOCIsIm5vbmNlIjoiNmE0MWI4YTQtZDE4ZC00ZTMxLWI1ZjgtZjM5YjE1ZGI1ODI3IiwidHlwZSI6WyJQUkVTRU5UQVRJT04iLCJFbWFpbCJdfQ.1GfPU-0eiRmaVDOqh0v8ptLdr3AHkU8iagtOGOmpzrZ55YmnLjLuZd8qx-RSQoDJ5U0NChv1lFFigtCpAEejAw";
68 |
69 | Jwt didJwt = Jwt.decode(jwt);
70 | Presentation presentation = Presentation.valueOf(didJwt);
71 | logger.debug("did: {}", didJwt);
72 | IssuerDid issuerDid = presentation.getIssuerDid();
73 | String did = issuerDid.getDid();
74 | String keyId = issuerDid.getKeyId();
75 | logger.debug("did: {}", did);
76 | logger.debug("keyId: {}", keyId);
77 |
78 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
79 | PublicKey pubKey = algorithm.byteToPublicKey(Hex.decode(TestKeys.PUBLIC_KEY_ES256));
80 |
81 |
82 | Jwt.VerifyResult verifyResult = didJwt.verify(pubKey);
83 | logger.debug("isVerify: {}", verifyResult);
84 | if (!verifyResult.isSuccess()) {
85 | return;
86 | }
87 |
88 | logger.debug("presentation: {}", presentation);
89 |
90 | List claims = presentation.getCredentials();
91 | for (String verifiableClaimJwt : claims) {
92 | logger.debug("verifiableClaimJwt: {}", verifiableClaimJwt);
93 | Jwt c = Jwt.decode(verifiableClaimJwt);
94 | Credential verifiableClaim = Credential.valueOf(c);
95 | IssuerDid i = verifiableClaim.getIssuerDid();
96 | String iDid = i.getDid();
97 | String iKeyId = i.getKeyId();
98 | logger.debug("idid: {}", iDid);
99 | logger.debug("ikeyId: {}", iKeyId);
100 |
101 | List type = verifiableClaim.getTypes();
102 | logger.debug("type: {}", type);
103 | Map claim = verifiableClaim.getClaim();
104 | logger.debug("claim: {}", claim);
105 |
106 | PublicKey p = algorithm.byteToPublicKey(Hex.decode(TestKeys.PUBLIC_KEY_ES256));
107 | verifyResult = c.verify(p);
108 | logger.debug("isVerify: {}", verifyResult);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/RepeatedTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import com.fasterxml.jackson.databind.JavaType;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import foundation.icon.did.core.Algorithm;
6 | import foundation.icon.did.core.AlgorithmProvider;
7 | import foundation.icon.did.core.KeyProvider;
8 | import foundation.icon.did.document.Document;
9 | import foundation.icon.did.document.EncodeType;
10 | import foundation.icon.did.exceptions.AlgorithmException;
11 | import foundation.icon.did.score.ScoreParameter;
12 | import foundation.icon.icx.IconService;
13 | import foundation.icon.icx.KeyWallet;
14 | import foundation.icon.icx.data.Address;
15 | import foundation.icon.icx.data.Bytes;
16 | import org.junit.jupiter.api.Disabled;
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.math.BigInteger;
23 | import java.util.ArrayList;
24 | import java.util.Collections;
25 | import java.util.List;
26 | import java.util.Objects;
27 | import java.util.concurrent.Executors;
28 | import java.util.concurrent.ThreadPoolExecutor;
29 | import java.util.stream.Collectors;
30 |
31 | @Disabled
32 | public class RepeatedTest {
33 |
34 | private static Logger logger = LoggerFactory.getLogger(RepeatedTest.class);
35 |
36 | private static int count = 0;
37 |
38 | public static void main(String[] args) throws InterruptedException, IOException {
39 | BigInteger networkId = new BigInteger("3");
40 | IconService iconService = IconServiceFactory.createLocal();
41 | Address scoreAddress = new Address("cx26484cf9cb42b6eebbf537fbfe6b7df3f86c5079");
42 | String keyId = "key";
43 |
44 | AlgorithmProvider.Type type = AlgorithmProvider.Type.ES256K;
45 | Algorithm algorithm = AlgorithmProvider.create(type);
46 |
47 | ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
48 | List documents = Collections.synchronizedList(new ArrayList<>());
49 | List wallets = loadMillionWalletJson(10);
50 | wallets.forEach(wallet -> {
51 | executorService.submit(() -> {
52 | try {
53 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
54 | String json = ScoreParameter.create(keyProvider, EncodeType.BASE64);
55 | DidService didService = new DidService(iconService, networkId, scoreAddress);
56 | Document doc = didService.create(wallet, json);
57 | documents.add(doc);
58 | System.out.println((count++) + " - " + doc.toJson());
59 | } catch (AlgorithmException | IOException e) {
60 | e.printStackTrace();
61 | }
62 | });
63 | });
64 |
65 | while (executorService.getActiveCount() > 0) {
66 | logger.debug("current active thread = " + executorService.getActiveCount());
67 | Thread.sleep(1000);
68 | }
69 |
70 | executorService.shutdown();
71 |
72 | logger.debug("count = " + count);
73 | logger.debug("expected count = " + wallets.size());
74 | logger.debug("document count = " + documents.size());
75 | }
76 |
77 | static List loadMillionWalletJson(int count) throws IOException {
78 | String path = Objects.requireNonNull(RepeatedTest.class.getClassLoader().getResource("investors.json")).getPath();
79 | // Path path = Paths.get(System.getProperty("user.dir"), "icon-sdk/keystore", "investors.json");
80 | File jsonFile = new File(path);
81 |
82 | ObjectMapper mapper = new ObjectMapper();
83 | JavaType type = mapper.getTypeFactory().
84 | constructCollectionType(List.class, String.class);
85 | List privateKeys = mapper.readValue(jsonFile, type);
86 | return privateKeys.stream()
87 | .limit(count)
88 | .map(privateKey -> {
89 | System.out.print(".");
90 | return KeyWallet.load(new Bytes(privateKey));
91 | })
92 | .collect(Collectors.toList());
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/TempFileProvider.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import org.junit.jupiter.api.BeforeEach;
4 |
5 | import java.io.File;
6 | import java.nio.file.Files;
7 |
8 |
9 |
10 | /**
11 | * Base class for tests wishing to use temporary file locations.
12 | */
13 | public class TempFileProvider {
14 | private File tempDir;
15 | protected String tempDirPath;
16 |
17 | @BeforeEach
18 | public void setUp() throws Exception {
19 | tempDir = Files.createTempDirectory(
20 | TempFileProvider.class.getSimpleName()).toFile();
21 | tempDirPath = tempDir.getPath();
22 | }
23 |
24 | public void tearDown() throws Exception {
25 | for (File file:tempDir.listFiles()) {
26 | file.delete();
27 | }
28 | tempDir.delete();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/TestKeys.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | /**
4 | * Test 용으로 사용할 Keypair
5 | */
6 | public class TestKeys {
7 |
8 | private TestKeys() {
9 | }
10 |
11 | public final static String PUBLIC_KEY_RS256 = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100baeeea62383467611bd54bf59584e0415e"
12 | + "f8f4821f6625f97b1d4b965a664c6cd2d9e7cfe0755dac2ef55876f5978678ff239a098f42ecf471658a637e13af39272d34"
13 | + "7c6d3efbae7299034a9dd8966d01af925c491bc3526aebec5750f149367010e9615fc2f9aa3654dd4b0e9e833bb14e92f329"
14 | + "7793e84a2f274276dbb6cc209d4f172268679eb0cb2b6af133651df98794f6fc82132a060410d4b9d32ae54cbe51c37955af"
15 | + "3c8dee2c456dd2454420031a66639266fb80bbc3567c7ac322c4bd29e576d27152aea85e365e5e71e02d76f921eb2dffee61"
16 | + "b67897e4d9ea095787fcd9423c5896a6c9eea1fa933bb0a0042dafbb472e5b0ae56c0bc876f61b0203010001";
17 |
18 | public final static String PRIVATE_KEY_RS256 = "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100baeeea62383467611bd54bf5"
19 | + "9584e0415ef8f4821f6625f97b1d4b965a664c6cd2d9e7cfe0755dac2ef55876f5978678ff239a098f42ecf471658a637e13"
20 | + "af39272d347c6d3efbae7299034a9dd8966d01af925c491bc3526aebec5750f149367010e9615fc2f9aa3654dd4b0e9e833b"
21 | + "b14e92f3297793e84a2f274276dbb6cc209d4f172268679eb0cb2b6af133651df98794f6fc82132a060410d4b9d32ae54cbe"
22 | + "51c37955af3c8dee2c456dd2454420031a66639266fb80bbc3567c7ac322c4bd29e576d27152aea85e365e5e71e02d76f921"
23 | + "eb2dffee61b67897e4d9ea095787fcd9423c5896a6c9eea1fa933bb0a0042dafbb472e5b0ae56c0bc876f61b020301000102"
24 | + "8201003de7d4300dcbf0f67c58b14c95a508fd2d1e061f3795c4faaf565ecb5e89a5429ebb32252a00c4323ae4de549af580"
25 | + "bf7e430486a8ee71796c3a43cfba177bbe52268accb0031d2742e5406d4c03c7a136df3579a16e73cb4e046e62e637d9d690"
26 | + "db50e681e79875d1835e3bb68e3108aa29cac9835089e771f5d6ab10a0a792b5ee36e77417ccfe1652e7cd1f9e7c0f240c50"
27 | + "c2883d325083f893a85a0d2f60898729daf09c332e4176b0a175312d091e31ba3a9d91d1611bf513d3c7cc20224c8bec7952"
28 | + "208e37e69038a08dc164dcd594eb84fdbacd512e30750c306b2abc1f2f19e51a67487c6e21fabbb6f6f1eff082e4fecc86ff"
29 | + "dd7d5410a63f703e1902818100eb3c851e2c65c5d3b5affa46324738d399e5ae7cb3a2ce5ec528dfb0e065accc44247164e4"
30 | + "8f989a82e8f0f4770ef304ddc4b7a03ed840e39c2ca5f4961fdeebd2d2619f98f7443b211ab979a72a237e2a6e9b24e49e55"
31 | + "87259045cdafc8e3f2feeea905aeaf724beab2d3a4c33a64f29330939275eefce6bf67407ac11768e902818100cb6eebf572"
32 | + "2d3f5e39643d2e2a5159ecd8dc062967716502aa19570d1372d1aa43c6a11a9de9dc3795237647861aab3ecd4b77bf79bfa9"
33 | + "e9b5c9d119085e34ee54aec5f84e232bb7e6b97d8b3f55ba13d3bf83177640ee65cd3f748f1565d190aeadbb8149e24c9116"
34 | + "2a97c80d639ef52d1b40af8ce8bf0a288058c030ffc46302818100a5a464082f332aee3d0dc1aa14555a8a85dfd9d22d9c02"
35 | + "bd710fab141daefad28b592e0fe171cbff61172e34b6716c668cd2ac8ac635f8db4d6993227b63cdd1390eb377727b0b2ca7"
36 | + "ceedb3e02627fffb590f1e176df6c3c78ba3db86606b42fc8889b45aa1685654d9bf76519298eac70279a7b42ba921c2bdae"
37 | + "05c259fda102818020b930ff84643ee33b3c2293407f6185b5c47ec13e40814d126b8d132f63b2d23ea0bedd77355d151bca"
38 | + "5e8656ce0769ccc02cfd01ea90bc655f9760fd7599f2147120ab367675dbd923514c8add91570b22ad45a2e202f72132e9de"
39 | + "f24434979f6196ddcf32b5ba48e48511cb05915642f1355087cc109ee3b0f195c8cbfb9d02818100d032dbbd3a7b4cb468ce"
40 | + "211e79b1525acde27cb424a5949cf77e6efe0bc608d34f13e11f9664381652075631498cf9a28fb9bcce80cf009a84d73d40"
41 | + "2ddb8cab16654944a8766b47f880dcf57a889db419bba840f8d436806fb504f3b43b6be16caedcc139ff4968ba21dea4fda0"
42 | + "3d48530782a0475964412eb8f4b62af93869";
43 |
44 | public final static String PUBLIC_KEY_ES256 = "3059301306072a8648ce3d020106082a8648ce3d030107034200049548b1aedbb7b812ef2412c7922cde2f9b358939877410cce4a6777ec1b651f17b5a169be5d175d5f801069653a429ccf42c7e6ff9223ffee957dbf8ff5de917";
45 |
46 | public final static String PRIVATE_KEY_ES256 = "308193020100301306072a8648ce3d020106082a8648ce3d03010704793077020101042059e7f78342999fc71dc12e63e6747d0a1c9059d3cf1140a2af9a1b7eb4e3e0dda00a06082a8648ce3d030107a144034200049548b1aedbb7b812ef2412c7922cde2f9b358939877410cce4a6777ec1b651f17b5a169be5d175d5f801069653a429ccf42c7e6ff9223ffee957dbf8ff5de917";
47 |
48 | public final static String ICON_WALLET_PRIVATE_KEY = "88251765d29d0415c1922b002a3cc291665d1f9fbdfec7671f35a952472755be";
49 |
50 | public final static String ISSUER_KEY_ID = "issuer";
51 |
52 | public final static String HOLDER_KEY_ID = "holder";
53 |
54 | public final static String TEMP_DID = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/core/AlgorithmProvider.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.icx.crypto.LinuxSecureRandom;
4 | import org.bouncycastle.crypto.RuntimeCryptoException;
5 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
6 |
7 | import java.security.Provider;
8 | import java.security.SecureRandom;
9 | import java.security.Security;
10 |
11 | /**
12 | * For test
13 | */
14 | @SuppressWarnings("Duplicates")
15 | public class AlgorithmProvider {
16 |
17 | public static final String PROVIDER = "BC";
18 |
19 | private static final SecureRandom SECURE_RANDOM;
20 | private static int isAndroid = -1;
21 |
22 | public static final double MIN_BOUNCY_CASTLE_VERSION = 1.54;
23 |
24 | static {
25 |
26 | if (isAndroidRuntime()) {
27 | new LinuxSecureRandom();
28 | }
29 |
30 | SECURE_RANDOM = new SecureRandom();
31 |
32 | Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
33 | Provider newProvider = new BouncyCastleProvider();
34 |
35 | if (newProvider.getVersion() < MIN_BOUNCY_CASTLE_VERSION) {
36 | String message = String.format(
37 | "The version of BouncyCastle should be %f or newer", MIN_BOUNCY_CASTLE_VERSION);
38 | throw new RuntimeCryptoException(message);
39 | }
40 |
41 | if (provider != null) {
42 | Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
43 | }
44 |
45 | Security.addProvider(newProvider);
46 |
47 | }
48 |
49 |
50 | public static Algorithm create(Type type) {
51 | if (type == null) {
52 | throw new IllegalArgumentException("type cannot be null.");
53 | }
54 | switch (type) {
55 | case RS256:
56 | return new RS256Algorithm();
57 | case ES256:
58 | return new ES256Algorithm();
59 | case ES256K:
60 | return new ES256KAlgorithm();
61 | case NONE:
62 | return new NoneAlgorithm();
63 | default:
64 | throw new IllegalArgumentException("cannot create sigAlgorithm for " + type);
65 | }
66 | }
67 |
68 | public enum Type {
69 | RS256("RsaVerificationKey2018", "SHA256withRSA", "RSA"),
70 | ES256("Secp256r1VerificationKey", "SHA256withECDSA", "EC"),
71 | ES256K("Secp256k1VerificationKey", "SHA256withECDSA", "EC"),
72 | NONE("none", "none", "none");
73 |
74 | private String identifier;
75 | private String sigAlgorithm;
76 | private String keyAlgorithm;
77 |
78 | Type(String identifier, String sigAlgorithm, String keyAlgorithm) {
79 | this.identifier = identifier;
80 | this.sigAlgorithm = sigAlgorithm;
81 | this.keyAlgorithm = keyAlgorithm;
82 | }
83 |
84 | public String getName() {
85 | return name();
86 | }
87 |
88 | public String getIdentifier() {
89 | return identifier;
90 | }
91 |
92 | public String getSigAlgorithm() {
93 | return sigAlgorithm;
94 | }
95 |
96 | public String getKeyAlgorithm() {
97 | return keyAlgorithm;
98 | }
99 |
100 | public static Type fromName(String name) {
101 | if (name != null) {
102 | for (Type t : Type.values()) {
103 | if (name.equalsIgnoreCase(t.getName())) {
104 | return t;
105 | }
106 | }
107 | }
108 | return null;
109 | }
110 |
111 | public static Type fromIdentifier(String identifier) {
112 | if (identifier != null) {
113 | for (Type t : Type.values()) {
114 | if (identifier.equalsIgnoreCase(t.getIdentifier())) {
115 | return t;
116 | }
117 | }
118 | }
119 | return null;
120 | }
121 | }
122 |
123 | public static SecureRandom secureRandom() {
124 | return SECURE_RANDOM;
125 | }
126 |
127 | public static boolean isAndroidRuntime() {
128 | if (isAndroid == -1) {
129 | final String runtime = System.getProperty("java.runtime.name");
130 | isAndroid = (runtime != null && runtime.equals("Android Runtime")) ? 1 : 0;
131 | }
132 | return isAndroid == 1;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/core/AlgorithmTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import org.bouncycastle.jce.interfaces.ECPublicKey;
4 | import org.bouncycastle.util.encoders.Hex;
5 | import org.junit.jupiter.api.Assertions;
6 | import org.junit.jupiter.api.BeforeEach;
7 | import org.junit.jupiter.api.RepeatedTest;
8 | import org.junit.jupiter.api.Test;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 | import java.nio.charset.StandardCharsets;
13 |
14 | public class AlgorithmTest {
15 |
16 | private final static Logger logger = LoggerFactory.getLogger(AlgorithmTest.class);
17 |
18 | byte[] message;
19 |
20 | @BeforeEach
21 | void setUp() {
22 | message = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaG9sZGVyIn0=.eyJjcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOaUlzSW10cFpDSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2phWE56ZFdWeUluMC5leUpqYkdGcGJTSTZleUpGYldGcGJDSTZJbUZoWVVCcFkyOXVMbVp2ZFc1a1lYUnBiMjRpZlN3aVpYaHdJam94TlRRM09ESXdNemcyTENKcFlYUWlPakUxTkRjM016TTVPRFlzSW1semN5STZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0p1YjI1alpTSTZJakF6TURjeFpqSmtMVGhpWlRBdE5EQXhOUzA0WTJJNExUZzRZVEkzTTJGaVpXWTJOaUlzSW5OMVlpSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0owZVhCbElqcGJJa1Z0WVdsc0lsMTkiXSwiZXhwIjoxNTQ1MjA5MTQyLCJpYXQiOjE1NDUyMDg4NDIsImlzcyI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJub25jZSI6IjZhNDFiOGE0LWQxOGQtNGUzMS1iNWY4LWYzOWIxNWRiNTgyNyIsInR5cGUiOlsiUFJFU0VOVEFUSU9OIiwiRW1haWwiXX0=".getBytes(StandardCharsets.UTF_8);
23 | }
24 |
25 | @RepeatedTest(100)
26 | void testES256K() throws Exception {
27 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
28 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
29 | byte[] signature = algorithm.sign(keyProvider.getPrivateKey(), message);
30 | logger.debug("message:{}", Hex.toHexString(message));
31 | logger.debug("signature:{}", Hex.toHexString(signature));
32 | ECPublicKey ecPublicKey = (ECPublicKey) keyProvider.getPublicKey();
33 | logger.debug("publicKey:{}", Hex.toHexString(ecPublicKey.getQ().getEncoded(false)));
34 | boolean verify = algorithm.verify(keyProvider.getPublicKey(), message, signature);
35 | Assertions.assertTrue(verify);
36 | }
37 |
38 | @Test
39 | void testRS256() throws Exception {
40 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.RS256);
41 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
42 | byte[] signature = algorithm.sign(keyProvider.getPrivateKey(), message);
43 | boolean verify = algorithm.verify(keyProvider.getPublicKey(), message, signature);
44 | Assertions.assertTrue(verify);
45 | }
46 |
47 | @RepeatedTest(100)
48 | void testES256() throws Exception {
49 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
50 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
51 | byte[] signature = algorithm.sign(keyProvider.getPrivateKey(), message);
52 | boolean verify = algorithm.verify(keyProvider.getPublicKey(), message, signature);
53 | Assertions.assertTrue(verify);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/core/KeyProviderTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 |
4 | import foundation.icon.did.exceptions.AlgorithmException;
5 | import foundation.icon.did.jwt.IssuerDid;
6 | import io.jsonwebtoken.ExpiredJwtException;
7 | import io.jsonwebtoken.Jwts;
8 | import io.jsonwebtoken.MalformedJwtException;
9 | import io.jsonwebtoken.security.SignatureException;
10 | import org.bouncycastle.crypto.params.ECDomainParameters;
11 | import org.bouncycastle.jce.ECNamedCurveTable;
12 | import org.bouncycastle.jce.interfaces.ECPublicKey;
13 | import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
14 | import org.bouncycastle.jce.spec.ECParameterSpec;
15 | import org.bouncycastle.jce.spec.ECPublicKeySpec;
16 | import org.bouncycastle.util.encoders.Hex;
17 | import org.junit.jupiter.api.Assertions;
18 | import org.junit.jupiter.api.BeforeEach;
19 | import org.junit.jupiter.api.Test;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | import java.io.File;
24 | import java.nio.charset.StandardCharsets;
25 | import java.nio.file.Files;
26 | import java.security.KeyFactory;
27 | import java.security.NoSuchAlgorithmException;
28 | import java.security.NoSuchProviderException;
29 | import java.security.PublicKey;
30 | import java.security.interfaces.RSAPrivateCrtKey;
31 | import java.security.spec.InvalidKeySpecException;
32 | import java.security.spec.RSAPublicKeySpec;
33 |
34 |
35 | public class KeyProviderTest {
36 |
37 | private static Logger logger = LoggerFactory.getLogger(KeyProviderTest.class);
38 |
39 | public File tempDir;
40 |
41 | private static File createTempDir() throws Exception {
42 | return Files.createTempDirectory(
43 | "testkeys").toFile();
44 | }
45 |
46 | @BeforeEach
47 | void setUp() throws Exception {
48 | tempDir = createTempDir();
49 | }
50 |
51 | @Test
52 | void testRS256Create() throws Exception {
53 | String keyId = "key-1";
54 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.RS256);
55 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
56 |
57 | logger.debug("didKeyHolder {}", keyProvider);
58 | Assertions.assertEquals(keyId, keyProvider.getKeyId());
59 | Assertions.assertEquals(AlgorithmProvider.Type.RS256, keyProvider.getType());
60 | }
61 |
62 | @Test
63 | void testES256Create() throws Exception {
64 | String keyId = "key-1";
65 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
66 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
67 |
68 | logger.debug("didKeyHolder {}", keyProvider);
69 | Assertions.assertEquals(keyId, keyProvider.getKeyId());
70 | Assertions.assertEquals(AlgorithmProvider.Type.ES256, keyProvider.getType());
71 | }
72 |
73 | @Test
74 | void testRS256PublicKey() throws Exception {
75 | String keyId = "rs256";
76 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.RS256);
77 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
78 | System.out.println(keyProvider.getPublicKey());
79 | System.out.println(Hex.toHexString(keyProvider.getPublicKey().getEncoded()));
80 |
81 | RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyProvider.getPrivateKey();
82 | RSAPublicKeySpec spec = new RSAPublicKeySpec(privateKey.getModulus(), privateKey.getPublicExponent());
83 | KeyFactory factory = KeyFactory.getInstance("RSA");
84 | PublicKey publicKey = factory.generatePublic(spec);
85 | System.out.println(publicKey);
86 | System.out.println(Hex.toHexString(publicKey.getEncoded()));
87 |
88 | byte[] message = "eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgjaG9sZGVyIn0=.eyJjcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOaUlzSW10cFpDSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2phWE56ZFdWeUluMC5leUpqYkdGcGJTSTZleUpGYldGcGJDSTZJbUZoWVVCcFkyOXVMbVp2ZFc1a1lYUnBiMjRpZlN3aVpYaHdJam94TlRRM09ESXdNemcyTENKcFlYUWlPakUxTkRjM016TTVPRFlzSW1semN5STZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0p1YjI1alpTSTZJakF6TURjeFpqSmtMVGhpWlRBdE5EQXhOUzA0WTJJNExUZzRZVEkzTTJGaVpXWTJOaUlzSW5OMVlpSTZJbVJwWkRwcFkyOXVPakF3TURBNU5qRmlObU5rTmpReU5UTm1Zakk0WXpsaU1HUXpaREl5TkdKbE5XWTVZakU0WkRRNVpqQXhaR0V6T1RCbU1EZ2lMQ0owZVhCbElqcGJJa1Z0WVdsc0lsMTkiXSwiZXhwIjoxNTQ1MjA5MTQyLCJpYXQiOjE1NDUyMDg4NDIsImlzcyI6ImRpZDppY29uOjAwMDA5NjFiNmNkNjQyNTNmYjI4YzliMGQzZDIyNGJlNWY5YjE4ZDQ5ZjAxZGEzOTBmMDgiLCJub25jZSI6IjZhNDFiOGE0LWQxOGQtNGUzMS1iNWY4LWYzOWIxNWRiNTgyNyIsInR5cGUiOlsiUFJFU0VOVEFUSU9OIiwiRW1haWwiXX0=".getBytes(StandardCharsets.UTF_8);
89 | byte[] signature = algorithm.sign(keyProvider.getPrivateKey(), message);
90 | boolean verify = algorithm.verify(publicKey, message, signature);
91 | System.out.println("verify:" + verify);
92 |
93 |
94 | String did = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
95 | spec = new RSAPublicKeySpec(privateKey.getModulus(), privateKey.getPublicExponent());
96 | factory = KeyFactory.getInstance("RSA");
97 | publicKey = factory.generatePublic(spec);
98 | System.out.println(publicKey);
99 |
100 |
101 | IssuerDid issuerDid = new IssuerDid.Builder()
102 | .did(did)
103 | .algorithm(keyProvider.getType().getName())
104 | .keyId(keyProvider.getKeyId())
105 | .build();
106 |
107 | String encodedJwt = issuerDid.buildJwt().sign(keyProvider.getPrivateKey());
108 |
109 | try {
110 | io.jsonwebtoken.Jws jwtparser = Jwts.parser()
111 | .setSigningKey(publicKey)
112 | .parseClaimsJws(encodedJwt);
113 | logger.debug("jwt parser:{}", jwtparser);
114 | } catch (ExpiredJwtException e) {
115 | e.printStackTrace();
116 | } catch (MalformedJwtException e) {
117 | e.printStackTrace();
118 | } catch (SignatureException e) {
119 | e.printStackTrace();
120 | } catch (IllegalArgumentException e) {
121 | e.printStackTrace();
122 | }
123 | }
124 |
125 | @Test
126 | void testES256KPublicKey() throws AlgorithmException {
127 | String keyId = "es256k";
128 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
129 | KeyProvider keyProvider = algorithm.generateKeyProvider(keyId);
130 | System.out.println(keyProvider.getPublicKey());
131 | byte[] pub = ((ECPublicKey) keyProvider.getPublicKey()).getQ().getEncoded(false);
132 |
133 | ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
134 | ECDomainParameters domain = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN());
135 | ECParameterSpec ecparameterSpec = new ECParameterSpec(spec.getCurve(), spec.getG(), spec.getN());
136 |
137 | try {
138 | KeyFactory fact = KeyFactory.getInstance("EC", "BC");
139 | PublicKey publicKey = fact.generatePublic(new ECPublicKeySpec(spec.getCurve().decodePoint(pub), ecparameterSpec));
140 | System.out.println(publicKey);
141 | } catch (NoSuchAlgorithmException e) {
142 | e.printStackTrace();
143 | } catch (NoSuchProviderException e) {
144 | e.printStackTrace();
145 | } catch (InvalidKeySpecException e) {
146 | e.printStackTrace();
147 | }
148 |
149 | }
150 | }
151 |
152 |
--------------------------------------------------------------------------------
/lib/src/test/java/foundation/icon/did/core/KeystoreTest.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.core;
2 |
3 | import foundation.icon.did.exceptions.AlgorithmException;
4 | import foundation.icon.did.exceptions.KeyPairException;
5 | import foundation.icon.did.exceptions.KeystoreException;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.Test;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 |
12 | public class KeystoreTest {
13 |
14 | private final String DID = "did:icon:0000961b6cd64253fb28c9b0d3d224be5f9b18d49f01da390f08";
15 | private final String FILE_NAME = DID + ".json";
16 | private final String PASSWORD = "ssw0rd";
17 |
18 | @Test
19 | void testES256() throws AlgorithmException, IOException, KeystoreException, KeyPairException {
20 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256);
21 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
22 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
23 | .did(DID)
24 | .build();
25 |
26 | Keystore.storeDidKeyHolder(PASSWORD, didKeyHolder, FILE_NAME);
27 | DidKeyHolder load = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
28 | assertEquals(didKeyHolder, load);
29 | }
30 |
31 | @Test
32 | void testRS256() throws AlgorithmException, IOException, KeystoreException, KeyPairException {
33 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.RS256);
34 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
35 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
36 | .did(DID)
37 | .build();
38 | Keystore.storeDidKeyHolder(PASSWORD, didKeyHolder, FILE_NAME);
39 | DidKeyHolder load = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
40 | assertEquals(didKeyHolder, load);
41 | }
42 |
43 | @Test
44 | void testES256K() throws AlgorithmException, IOException, KeystoreException, KeyPairException {
45 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
46 | KeyProvider keyProvider = algorithm.generateKeyProvider("key1");
47 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
48 | .did(DID)
49 | .build();
50 | Keystore.storeDidKeyHolder(PASSWORD, didKeyHolder, FILE_NAME);
51 | DidKeyHolder load = Keystore.loadDidKeyHolder(PASSWORD, new File(FILE_NAME));
52 | assertEquals(didKeyHolder, load);
53 | }
54 |
55 | private void assertEquals(DidKeyHolder expected, DidKeyHolder actual) {
56 | Assertions.assertEquals(DID, actual.getDid());
57 | Assertions.assertEquals(expected.getKeyId(), actual.getKeyId());
58 | Assertions.assertEquals(expected.getType(), actual.getType());
59 | Algorithm algorithm = AlgorithmProvider.create(expected.getType());
60 | Assertions.assertArrayEquals(algorithm.privateKeyToByte(expected.getPrivateKey()),
61 | algorithm.privateKeyToByte(actual.getPrivateKey()));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec256-key-pair.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN EC PRIVATE KEY-----
2 | MHcCAQEEIDxiRgJuF9X7wbgtc0qTv+CM8ej13zTGoimkuUVJBahBoAoGCCqGSM49
3 | AwEHoUQDQgAEQgb5npLHd0Bk61bNnjK632uwmBfrF7I8hoPgaOZjyhh+BrPDO6CL
4 | 6D/aW/yPObXXm7SpZogmRwGROcOA3yUleg==
5 | -----END EC PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec256-key-private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPGJGAm4X1fvBuC1z
3 | SpO/4Izx6PXfNMaiKaS5RUkFqEGhRANCAARCBvmeksd3QGTrVs2eMrrfa7CYF+sX
4 | sjyGg+Bo5mPKGH4Gs8M7oIvoP9pb/I85tdebtKlmiCZHAZE5w4DfJSV6
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec256-key-public-invalid.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjT
3 | CLQeb042TjiMJxG+9DLFmRSMlBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
4 | -----END PUBLIC KEY-----
5 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec256-key-public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQgb5npLHd0Bk61bNnjK632uwmBfr
3 | F7I8hoPgaOZjyhh+BrPDO6CL6D/aW/yPObXXm7SpZogmRwGROcOA3yUleg==
4 | -----END PUBLIC KEY-----
5 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec384-key-pair.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN EC PRIVATE KEY-----
2 | MIGkAgEBBDCVWQsOJHjKD0I4cXOYJm4G8i5c7IMhFbxFq57OUlrTVmND43dvvNW1
3 | oQ6i6NiXEQWgBwYFK4EEACKhZANiAASezSGlAu4wAaJe4676mQM0F/5slI+Ekdpt
4 | RJdfsQP9mNxe7RdzHgcSw7j/Wxa45nlnFnFrPPL4viJKOBRxMB1jjVA9my9PixxJ
5 | GoB22qDQwFbP8ldmEp6abwdBsXNaePM=
6 | -----END EC PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec384-key-private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCVWQsOJHjKD0I4cXOY
3 | Jm4G8i5c7IMhFbxFq57OUlrTVmND43dvvNW1oQ6i6NiXEQWhZANiAASezSGlAu4w
4 | AaJe4676mQM0F/5slI+EkdptRJdfsQP9mNxe7RdzHgcSw7j/Wxa45nlnFnFrPPL4
5 | viJKOBRxMB1jjVA9my9PixxJGoB22qDQwFbP8ldmEp6abwdBsXNaePM=
6 | -----END PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec384-key-public-invalid.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEJ0tamPyAJVUhDO1DlceSYCdA9WKVX6nO
3 | K4VYetXvqmMKdyVkaoA4Gl02KoVLujiSSSAE6oK/Hf7x2fagaE9LgJdJxg07Ip+T
4 | C6cgFi2HHDeXG7djB5Zl1TKA9/w/8iW5
5 | -----END PUBLIC KEY-----
6 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec384-key-public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEns0hpQLuMAGiXuOu+pkDNBf+bJSPhJHa
3 | bUSXX7ED/ZjcXu0Xcx4HEsO4/1sWuOZ5ZxZxazzy+L4iSjgUcTAdY41QPZsvT4sc
4 | SRqAdtqg0MBWz/JXZhKemm8HQbFzWnjz
5 | -----END PUBLIC KEY-----
6 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec512-key-pair.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN EC PRIVATE KEY-----
2 | MIHbAgEBBEHzl1DpZSQJ8YhCbN/uvo5SOu0BjDDX9Gub6zsBW6B2TxRzb5sBeQaW
3 | VscDUZha4Xr1HEWpVtua9+nEQU/9Aq9Pl6AHBgUrgQQAI6GBiQOBhgAEAJhvCa6S
4 | 89ePqlLO6MRV9KQqHvdAITDAf/WRDcvCmfrrNuov+j4gQXO12ohIukPCHM9rYms8
5 | Eqciz3gaxVTxZD4CAA8i2k9H6ew9iSh1qXa1kLxiyzMBqmAmmg4u/SroD6OleG56
6 | SwZVbWx+KIINB6r/PQVciGX8FjwgR/mbLHotVZYD
7 | -----END EC PRIVATE KEY-----
8 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec512-key-private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIHtAgEAMBAGByqGSM49AgEGBSuBBAAjBIHVMIHSAgEBBEHzl1DpZSQJ8YhCbN/u
3 | vo5SOu0BjDDX9Gub6zsBW6B2TxRzb5sBeQaWVscDUZha4Xr1HEWpVtua9+nEQU/9
4 | Aq9Pl6GBiQOBhgAEAJhvCa6S89ePqlLO6MRV9KQqHvdAITDAf/WRDcvCmfrrNuov
5 | +j4gQXO12ohIukPCHM9rYms8Eqciz3gaxVTxZD4CAA8i2k9H6ew9iSh1qXa1kLxi
6 | yzMBqmAmmg4u/SroD6OleG56SwZVbWx+KIINB6r/PQVciGX8FjwgR/mbLHotVZYD
7 | -----END PRIVATE KEY-----
8 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec512-key-public-invalid.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgtBWt9rVtdQPdeoChvCXnXHvkg/F
3 | 41AAubIVd+3yTvLFmxuHuaor9CHl7FlT3532mUG+GG0EEw5UuYkFrg/ABBgAfuVf
4 | wO1u0V0wJPkmpxcnZoojFaAOKcsBvUvDulbBh0HhAyd+nlfZquvV43uwFVpn2Cjb
5 | Lx+/AT1PE6Muqy4JkGU=
6 | -----END PUBLIC KEY-----
7 |
--------------------------------------------------------------------------------
/lib/src/test/resources/ec512-key-public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAmG8JrpLz14+qUs7oxFX0pCoe90Ah
3 | MMB/9ZENy8KZ+us26i/6PiBBc7XaiEi6Q8Icz2tiazwSpyLPeBrFVPFkPgIADyLa
4 | T0fp7D2JKHWpdrWQvGLLMwGqYCaaDi79KugPo6V4bnpLBlVtbH4ogg0Hqv89BVyI
5 | ZfwWPCBH+Zssei1VlgM=
6 | -----END PUBLIC KEY-----
7 |
--------------------------------------------------------------------------------
/lib/src/test/resources/rsa-private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4ZtdaIrd1BPIJ
3 | tfnF0TjIK5inQAXZ3XlCrUlJdP+XHwIRxdv1FsN12XyMYO/6ymLmo9ryoQeIrsXB
4 | XYqlET3zfAY+diwCb0HEsVvhisthwMU4gZQu6TYW2s9LnXZB5rVtcBK69hcSlA2k
5 | ZudMZWxZcj0L7KMfO2rIvaHw/qaVOE9j0T257Z8Kp2CLF9MUgX0ObhIsdumFRLaL
6 | DvDUmBPr2zuh/34j2XmWwn1yjN/WvGtdfhXW79Ki1S40HcWnygHgLV8sESFKUxxQ
7 | mKvPUTwDOIwLFL5WtE8Mz7N++kgmDcmWMCHc8kcOIu73Ta/3D4imW7VbKgHZo9+K
8 | 3ESFE3RjAgMBAAECggEBAJTEIyjMqUT24G2FKiS1TiHvShBkTlQdoR5xvpZMlYbN
9 | tVWxUmrAGqCQ/TIjYnfpnzCDMLhdwT48Ab6mQJw69MfiXwc1PvwX1e9hRscGul36
10 | ryGPKIVQEBsQG/zc4/L2tZe8ut+qeaK7XuYrPp8bk/X1e9qK5m7j+JpKosNSLgJj
11 | NIbYsBkG2Mlq671irKYj2hVZeaBQmWmZxK4fw0Istz2WfN5nUKUeJhTwpR+JLUg4
12 | ELYYoB7EO0Cej9UBG30hbgu4RyXA+VbptJ+H042K5QJROUbtnLWuuWosZ5ATldwO
13 | u03dIXL0SH0ao5NcWBzxU4F2sBXZRGP2x/jiSLHcqoECgYEA4qD7mXQpu1b8XO8U
14 | 6abpKloJCatSAHzjgdR2eRDRx5PMvloipfwqA77pnbjTUFajqWQgOXsDTCjcdQui
15 | wf5XAaWu+TeAVTytLQbSiTsBhrnoqVrr3RoyDQmdnwHT8aCMouOgcC5thP9vQ8Us
16 | rVdjvRRbnJpg3BeSNimH+u9AHgsCgYEA0EzcbOltCWPHRAY7B3Ge/AKBjBQr86Kv
17 | TdpTlxePBDVIlH+BM6oct2gaSZZoHbqPjbq5v7yf0fKVcXE4bSVgqfDJ/sZQu9Lp
18 | PTeV7wkk0OsAMKk7QukEpPno5q6tOTNnFecpUhVLLlqbfqkB2baYYwLJR3IRzboJ
19 | FQbLY93E8gkCgYB+zlC5VlQbbNqcLXJoImqItgQkkuW5PCgYdwcrSov2ve5r/Acz
20 | FNt1aRdSlx4176R3nXyibQA1Vw+ztiUFowiP9WLoM3PtPZwwe4bGHmwGNHPIfwVG
21 | m+exf9XgKKespYbLhc45tuC08DATnXoYK7O1EnUINSFJRS8cezSI5eHcbQKBgQDC
22 | PgqHXZ2aVftqCc1eAaxaIRQhRmY+CgUjumaczRFGwVFveP9I6Gdi+Kca3DE3F9Pq
23 | PKgejo0SwP5vDT+rOGHN14bmGJUMsX9i4MTmZUZ5s8s3lXh3ysfT+GAhTd6nKrIE
24 | kM3Nh6HWFhROptfc6BNusRh1kX/cspDplK5x8EpJ0QKBgQDWFg6S2je0KtbV5PYe
25 | RultUEe2C0jYMDQx+JYxbPmtcopvZQrFEur3WKVuLy5UAy7EBvwMnZwIG7OOohJb
26 | vkSpADK6VPn9lbqq7O8cTedEHttm6otmLt8ZyEl3hZMaL3hbuRj6ysjmoFKx6CrX
27 | rK0/Ikt5ybqUzKCMJZg2VKGTxg==
28 | -----END PRIVATE KEY-----
--------------------------------------------------------------------------------
/lib/src/test/resources/rsa-public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGbXWiK3dQTyCbX5xdE4
3 | yCuYp0AF2d15Qq1JSXT/lx8CEcXb9RbDddl8jGDv+spi5qPa8qEHiK7FwV2KpRE9
4 | 83wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVs
5 | WXI9C+yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT
6 | 69s7of9+I9l5lsJ9cozf1rxrXX4V1u/SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8
7 | AziMCxS+VrRPDM+zfvpIJg3JljAh3PJHDiLu902v9w+Iplu1WyoB2aPfitxEhRN0
8 | YwIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/lib/src/test/resources/rsa-public_invalid.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzYuc22QSst/dS7geYYK
3 | 5l5kLxU0tayNdixkEQ17ix+CUcUbKIsnyftZxaCYT46rQtXgCaYRdJcbB3hmyrOa
4 | vkhTpX79xJZnQmfuamMbZBqitvscxW9zRR9tBUL6vdi/0rpoUwPMEh8+Bw7CgYR0
5 | FK0DhWYBNDfe9HKcyZEv3max8Cdq18htxjEsdYO0iwzhtKRXomBWTdhD5ykd/fAC
6 | VTr4+KEY+IeLvubHVmLUhbE5NgWXxrRpGasDqzKhCTmsa2Ysf712rl57SlH0Wz/M
7 | r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s
8 | YwIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/sample/README.md:
--------------------------------------------------------------------------------
1 | ## Sample
2 |
3 | `did-sdk-java` 의 샘플 모음
4 |
5 | - KeyProviderSample : KeyProvider 생성 샘플
6 | - DidManageSample : DID Document Create, Add Key, Revoke Key, Read 샘플
7 | - CredentialSample : Owner 가 Issuer 에게 Credential 요청하고 발급받아 확인하는 샘플
8 | - PresentationSample : Owner 가 Presentation 을 생성하고 Verifier 에게 전달해서 Verifier 가 Claim 을 확인하는 샘플
9 | - ClientToIssuerSample : Client 에서 Issuer(Server) 와 연동해서 Credential 요청하고 발급받아 확인하는 샘플
10 |
11 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'io.franzbecker.gradle-lombok' version '1.14'
4 | }
5 |
6 | sourceCompatibility = 1.8
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | ext {
13 | logbackVersion = '1.2.3'
14 | iconSdkVersion = '0.9.11'
15 | gsonVersion = '2.8.0'
16 | retrofitVersion = '2.5.0'
17 | okhttpVersion = '3.12.1'
18 | }
19 |
20 | dependencies {
21 | // implementation fileTree(dir: 'libs', include: '*.jar')
22 | implementation project(':lib')
23 | implementation "ch.qos.logback:logback-classic:$logbackVersion"
24 | implementation "foundation.icon:icon-sdk:$iconSdkVersion"
25 | implementation "com.google.code.gson:gson:$gsonVersion"
26 |
27 | implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
28 | implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"
29 | implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
30 | }
31 |
32 | lombok {
33 | sha256 = ""
34 | }
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/CredentialSample.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/CredentialSample.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/DidManageSample.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/DidManageSample.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/KeyPoviderSample.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/KeyPoviderSample.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/PresentationSample.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/PresentationSample.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/api/ApiResponse.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/api/ApiResponse.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/api/AuthResponse.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/api/AuthResponse.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/api/ClaimIssueApi$Api.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/api/ClaimIssueApi$Api.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/api/ClaimIssueApi.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/api/ClaimIssueApi.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/api/CredentialResponse.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/api/CredentialResponse.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/config/DevConfig.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/config/DevConfig.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/config/LocalConfig.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/config/LocalConfig.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/config/SampleConfig.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/config/SampleConfig.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/config/SampleKeys.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/config/SampleKeys.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/exception/SampleException.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/exception/SampleException.class
--------------------------------------------------------------------------------
/sample/build/classes/java/main/foundation/icon/did/util/FileUtils.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/classes/java/main/foundation/icon/did/util/FileUtils.class
--------------------------------------------------------------------------------
/sample/build/libs/sample-0.8.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icon-project/did-sdk-java/19a33032576cf676ce541eb1f3b10bdf5bdbb8d4/sample/build/libs/sample-0.8.3.jar
--------------------------------------------------------------------------------
/sample/build/tmp/jar/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 |
3 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/DidManageSample.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 | import foundation.icon.did.config.SampleConfig;
4 | import foundation.icon.did.config.SampleKeys;
5 | import foundation.icon.did.core.*;
6 | import foundation.icon.did.document.Document;
7 | import foundation.icon.did.document.EncodeType;
8 | import foundation.icon.did.exception.SampleException;
9 | import foundation.icon.did.exceptions.AlgorithmException;
10 | import foundation.icon.did.exceptions.KeyPairException;
11 | import foundation.icon.did.exceptions.KeystoreException;
12 | import foundation.icon.did.jwt.Jwt;
13 | import foundation.icon.did.score.ScoreParameter;
14 | import foundation.icon.icx.IconService;
15 | import foundation.icon.icx.KeyWallet;
16 | import foundation.icon.icx.data.Address;
17 | import foundation.icon.icx.data.Bytes;
18 | import foundation.icon.icx.data.IconAmount;
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.math.BigInteger;
25 |
26 | @SuppressWarnings("Duplicates")
27 | public class DidManageSample {
28 |
29 | public static Logger logger = LoggerFactory.getLogger(DidManageSample.class);
30 |
31 | public static void printDocument(Document document) {
32 | logger.debug("DID Document : {}", document);
33 | logger.debug("DID Document json: {}\n", document.toJson());
34 | }
35 |
36 | public static void main(String[] args) throws IOException, KeystoreException, KeyPairException {
37 |
38 | // Create objects for connecting ICON Network
39 | SampleConfig config = SampleConfig.local();
40 | BigInteger networkId = config.getNetworkId();
41 | IconService iconService = config.iconService();
42 |
43 | // DID Document Score Address
44 | Address scoreAddress = config.getScoreAddress();
45 |
46 | // Create the DidService object
47 | DidService didService = new DidService(iconService, networkId, scoreAddress);
48 |
49 | KeyWallet wallet = KeyWallet.load(new Bytes(SampleKeys.ISSUER_WALLET_PRIVATE_KEY));
50 | BigInteger balance = iconService.getBalance(wallet.getAddress()).execute();
51 | if (balance.compareTo(IconAmount.of("1", IconAmount.Unit.ICX).toLoop()) < 0) {
52 | throw new SampleException("the balance of " + wallet.getAddress() + " < 1 icx\n Use your KeyWallet");
53 | }
54 |
55 | logger.debug(" ### CREATE DID Document");
56 | // the id for publicKey/privateKey
57 | String keyId = "sampleKey1";
58 |
59 | // Generate a new KeyProvider object
60 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
61 | KeyProvider keyProvider = null;
62 | try {
63 | keyProvider = algorithm.generateKeyProvider(keyId);
64 | } catch (Exception e) {
65 | throw new SampleException("KeyProvider creation failed");
66 | }
67 | logger.debug("key provider : {}", keyProvider);
68 |
69 | EncodeType encodeType = EncodeType.BASE64;
70 |
71 | // Send a transaction to create a DID document
72 | Document document = null;
73 | try {
74 | String json = ScoreParameter.create(keyProvider, encodeType);
75 | document = didService.create(wallet, json);
76 | } catch (IOException e) {
77 | throw new SampleException("DID document creation failed \n" + e.getMessage());
78 | }
79 |
80 | // print DID Document
81 | printDocument(document);
82 |
83 | logger.debug(" ### Store the key information for using did.");
84 | String password = "P@ssw0rd";
85 | File file = new File("./");
86 | DidKeyHolder didKeyHolder = new DidKeyHolder.Builder(keyProvider)
87 | .did(document.getId())
88 | .build();
89 | Keystore.storeDidKeyHolder(password, didKeyHolder, file);
90 | DidKeyHolder k = Keystore.loadDidKeyHolder(password, new File(document.getId() + ".json"));
91 | logger.debug("load KeyProvider : {}\n", k);
92 |
93 | logger.debug(" ### READ Document");
94 | // Get a id of DID Document
95 | String did = document.getId();
96 | logger.debug("DID : {}", did);
97 |
98 | try {
99 | document = didService.readDocument(did);
100 | } catch (IOException e) {
101 | throw new SampleException(e.getMessage());
102 | }
103 |
104 | // print DID Document
105 | printDocument(document);
106 |
107 |
108 | logger.debug(" ### Add public key");
109 | // the id of publicKey/privateKey to add
110 | String newKeyId = "sampleKey2";
111 |
112 | // Generate a new KeyProvider object
113 | KeyProvider newKeyProvider = null;
114 | algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
115 | try {
116 | newKeyProvider = algorithm.generateKeyProvider(newKeyId);
117 | } catch (Exception e) {
118 | throw new SampleException("KeyProvider creation failed");
119 | }
120 | logger.debug("add key porvider : {}", keyProvider);
121 |
122 | encodeType = EncodeType.BASE64;
123 |
124 | // Send a transaction to add a publicKey to the DID document
125 | try {
126 | Jwt addJwt = ScoreParameter.addKey(didKeyHolder, newKeyProvider, encodeType);
127 | document = didService.addPublicKey(wallet, didKeyHolder.sign(addJwt));
128 | } catch (IOException e) {
129 | throw new SampleException("Failed to add public key \n" + e.getMessage());
130 | } catch (AlgorithmException e) {
131 | throw new SampleException("Failed to sign \n" + e.getMessage());
132 | }
133 |
134 | // print DID Document
135 | printDocument(document);
136 |
137 | logger.debug(" ### Revoke public key");
138 | logger.debug("revoke key id : {}", newKeyId);
139 | try {
140 | Jwt revokeJwt = ScoreParameter.revokeKey(didKeyHolder, newKeyId);
141 | document = didService.revokeKey(wallet, didKeyHolder.sign(revokeJwt));
142 | } catch (IOException e) {
143 | throw new SampleException("Failed to revoke public key \n" + e.getMessage());
144 | } catch (AlgorithmException e) {
145 | throw new SampleException("Failed to sign \n" + e.getMessage());
146 | }
147 |
148 | // print DID Document
149 | printDocument(document);
150 |
151 | logger.debug(" ### The end");
152 |
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/KeyPoviderSample.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did;
2 |
3 |
4 | import foundation.icon.did.core.Algorithm;
5 | import foundation.icon.did.core.AlgorithmProvider;
6 | import foundation.icon.did.core.KeyProvider;
7 | import org.bouncycastle.util.encoders.Hex;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | class KeyPoviderSample {
12 |
13 | private static Logger logger = LoggerFactory.getLogger(KeyPoviderSample.class);
14 |
15 |
16 | /**
17 | * Create a new KeyProvider using Secp256k algorithm.
18 | */
19 | private KeyProvider generateES256K() throws Exception {
20 | String keyId = "new-ES256Key";
21 | Algorithm algorithm = AlgorithmProvider.create(AlgorithmProvider.Type.ES256K);
22 | return algorithm.generateKeyProvider(keyId);
23 | }
24 |
25 | public static void main(String[] args) throws Exception {
26 |
27 | KeyPoviderSample sample = new KeyPoviderSample();
28 |
29 | // Create a new KeyProvider
30 | KeyProvider keyProvider = sample.generateES256K();
31 | logger.debug("new ES256K KeyProvider : {}", keyProvider);
32 |
33 | // Create the algorithm object
34 | Algorithm algorithm = AlgorithmProvider.create(keyProvider.getType());
35 | // Important information that user need to have
36 | String keyId = keyProvider.getKeyId();
37 | String type = keyProvider.getType().getName();
38 | String privateKey = Hex.toHexString(algorithm.privateKeyToByte(keyProvider.getPrivateKey()));
39 | String publicKey = Hex.toHexString(algorithm.publicKeyToByte(keyProvider.getPublicKey()));
40 |
41 | // Create a KeyProvider from each String
42 | algorithm = AlgorithmProvider.create(keyProvider.getType());
43 | KeyProvider loadKeyProvider = new KeyProvider.Builder()
44 | .keyId(keyId)
45 | .publicKey(algorithm.byteToPublicKey(Hex.decode(publicKey)))
46 | .privateKey(algorithm.byteToPrivateKey(Hex.decode(privateKey)))
47 | .type(AlgorithmProvider.Type.fromName(type))
48 | .build();
49 |
50 | logger.debug("loadDidKeyHolder == didKeyHolder : {}", keyProvider.equals(loadKeyProvider));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/api/ApiResponse.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.api;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @ToString
8 | @NoArgsConstructor
9 | @AllArgsConstructor
10 | public class ApiResponse {
11 | Boolean success;
12 | String message;
13 |
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/api/AuthResponse.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.api;
2 |
3 | import lombok.Getter;
4 | import lombok.ToString;
5 |
6 | @Getter
7 | @ToString
8 | public class AuthResponse extends ApiResponse {
9 | String token;
10 | }
11 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/api/ClaimIssueApi.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.api;
2 |
3 | import com.google.gson.Gson;
4 | import retrofit2.Call;
5 | import retrofit2.Response;
6 | import retrofit2.Retrofit;
7 | import retrofit2.http.Body;
8 | import retrofit2.http.POST;
9 |
10 | import java.io.IOException;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | public class ClaimIssueApi {
15 |
16 | private Api api;
17 |
18 | public ClaimIssueApi(Retrofit retrofit) {
19 | this.api = retrofit.create(Api.class);
20 | }
21 |
22 | public AuthResponse checkOwner(String authType, String value, String didToken) throws IOException {
23 | Map params = new HashMap<>();
24 | params.put("type", authType);
25 | params.put("value", value);
26 | params.put("token", didToken);
27 | Response response = api.checkOwner(params).execute();
28 | if (response.isSuccessful())
29 | return response.body();
30 | else {
31 | return new Gson().fromJson(response.errorBody().charStream(), AuthResponse.class);
32 | }
33 | }
34 |
35 | public CredentialResponse sendCredentialClaim(String authNum, String didToken) throws IOException {
36 | Map params = new HashMap<>();
37 | params.put("authNum", authNum);
38 | params.put("authToken", didToken);
39 | Response response = api.sendCredentialClaim(params).execute();
40 | if (response.isSuccessful())
41 | return response.body();
42 | else {
43 | return new Gson().fromJson(response.errorBody().charStream(), CredentialResponse.class);
44 | }
45 | }
46 |
47 | interface Api {
48 | @POST("/v1/issuer/checkOwner")
49 | Call checkOwner(@Body Map params);
50 |
51 | @POST("/v1/issuer/sendCredentialClaim")
52 | Call sendCredentialClaim(@Body Map params);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/api/CredentialResponse.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.api;
2 |
3 | import lombok.Getter;
4 | import lombok.ToString;
5 |
6 | @Getter
7 | @ToString
8 | public class CredentialResponse extends ApiResponse {
9 | String credentialClaim;
10 | }
11 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/config/DevConfig.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.config;
2 |
3 | import foundation.icon.icx.data.Address;
4 | import lombok.AccessLevel;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.math.BigInteger;
8 |
9 | @NoArgsConstructor(access = AccessLevel.PACKAGE)
10 | final public class DevConfig implements SampleConfig {
11 | private String nodeUrl = "https://test-ctz.solidwallet.io/api/v3";
12 | private BigInteger networkId = BigInteger.valueOf(2);
13 |
14 | @Override
15 | public String getNodeUrl() {
16 | return nodeUrl;
17 | }
18 |
19 | @Override
20 | public BigInteger getNetworkId() {
21 | return networkId;
22 | }
23 |
24 | @Override
25 | public Address getScoreAddress() {
26 | return new Address("cx9a96c0dcf0567635309809d391908c32fcca5310");
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/config/LocalConfig.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.config;
2 |
3 | import foundation.icon.icx.data.Address;
4 | import lombok.AccessLevel;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.math.BigInteger;
8 |
9 | @NoArgsConstructor(access = AccessLevel.PACKAGE)
10 | final public class LocalConfig implements SampleConfig {
11 | private final String nodeUrl = "http://localhost:9000/api/v3";
12 | private BigInteger networkId = BigInteger.valueOf(3);
13 |
14 | @Override
15 | public String getNodeUrl() {
16 | return nodeUrl;
17 | }
18 |
19 | @Override
20 | public BigInteger getNetworkId() {
21 | return networkId;
22 | }
23 |
24 | @Override
25 | public Address getScoreAddress() {
26 | return new Address("cx26484cf9cb42b6eebbf537fbfe6b7df3f86c5079");
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/config/SampleConfig.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.config;
2 |
3 | import foundation.icon.icx.IconService;
4 | import foundation.icon.icx.data.Address;
5 | import foundation.icon.icx.transport.http.HttpProvider;
6 | import okhttp3.OkHttpClient;
7 | import okhttp3.logging.HttpLoggingInterceptor;
8 |
9 | import java.math.BigInteger;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | public interface SampleConfig {
13 |
14 | String OWNER_KEY_FILE_NAME = "owner.json";
15 | String ISSUER_KEY_FILE_NAME = "issuer.json";
16 | String CREDENTIAL_FILE_NAME = "credential.json";
17 | String PRESENTATION_FILE_NAME = "presentation.json";
18 |
19 | String TEST_PASSWORD = "P@ssw0rd";
20 |
21 | boolean DEBUG = false;
22 |
23 | String getNodeUrl();
24 |
25 | BigInteger getNetworkId();
26 |
27 | Address getScoreAddress();
28 |
29 | default IconService iconService() {
30 | return new IconService(createHttpProvider(getNodeUrl()));
31 | }
32 |
33 | default HttpProvider createHttpProvider(String url) {
34 | if (!DEBUG) {
35 | return new HttpProvider(url);
36 | } else {
37 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
38 | logging.setLevel(HttpLoggingInterceptor.Level.BODY);
39 | OkHttpClient httpClient = new OkHttpClient.Builder()
40 | .addInterceptor(logging)
41 | .readTimeout(100L, TimeUnit.SECONDS)
42 | .build();
43 | return new HttpProvider(httpClient, url);
44 | }
45 | }
46 |
47 | static SampleConfig dev() {
48 | return new DevConfig();
49 | }
50 |
51 | static SampleConfig local() {
52 | return new LocalConfig();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/config/SampleKeys.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.config;
2 |
3 | /**
4 | * Sample Keypair
5 | */
6 | public class SampleKeys {
7 |
8 | private SampleKeys() {
9 | }
10 |
11 | // hx797a20d278b8aca4fb1927d80a79aab88b328cf3
12 | public final static String ISSUER_WALLET_PRIVATE_KEY = "a03694b07ab48f01e8f617e4c2d3953fcae8a0347d17a14a426030ff0de05e41";
13 |
14 | public final static String ISSUER_KEY_ID = "EmailIssuer";
15 |
16 | // hx228ffa8cf35d6ce624a527f7442e5dc94b82eb74
17 | public final static String OWNER_WALLET_PRIVATE_KEY = "a03694b07ab48f01e8f617e4c2d3953fcae8a0347d17a14a426030ff0de05e41";
18 |
19 | public final static String OWNER_PUBLIC_KEY_ES256 = "3059301306072a8648ce3d020106082a8648ce3d030107034200041b6b33dc71175b5117a61f2738aa6d593812847cc5afebdca19808ef0e3f056e79a2e3bfd84219a8d7f3a453100e31cb5867936f244820f18da69ef435c530c9";
20 |
21 | public final static String OWNER_PRIVATE_KEY_ES256 = "308193020100301306072a8648ce3d020106082a8648ce3d03010704793077020101042063e447fa7d6d4d99c180b6a51cc829ded2c106bb46b35dd9142f349bcd8c560ea00a06082a8648ce3d030107a144034200041b6b33dc71175b5117a61f2738aa6d593812847cc5afebdca19808ef0e3f056e79a2e3bfd84219a8d7f3a453100e31cb5867936f244820f18da69ef435c530c9";
22 |
23 | public final static String OWNER_KEY_ID = "owner";
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/exception/SampleException.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.exception;
2 |
3 | public class SampleException extends RuntimeException {
4 |
5 | public SampleException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/sample/src/main/java/foundation/icon/did/util/FileUtils.java:
--------------------------------------------------------------------------------
1 | package foundation.icon.did.util;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonParser;
7 |
8 | import java.io.*;
9 |
10 | public class FileUtils {
11 |
12 | public static void writeClaim(String fileName, String key, String value) {
13 | JsonObject object = new JsonObject();
14 | object.addProperty(key, value);
15 |
16 | try (Writer writer = new FileWriter(fileName)) {
17 | Gson gson = new GsonBuilder().create();
18 | gson.toJson(object, writer);
19 | } catch (IOException e) {
20 | e.printStackTrace();
21 | }
22 | }
23 |
24 | public static String loadClaim(String fileName, String key) throws FileNotFoundException {
25 | InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName));
26 | JsonParser parser = new JsonParser();
27 | JsonObject object = parser.parse(reader).getAsJsonObject();
28 | return object.get(key).getAsString();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'did-sdk-java'
2 | include 'lib'
3 | include 'sample'
4 |
5 |
--------------------------------------------------------------------------------