Skip to content

Commit 6bae727

Browse files
committed
Add Java implementation
1 parent 12473fc commit 6bae727

File tree

5 files changed

+172
-20
lines changed

5 files changed

+172
-20
lines changed

java/wsgup/app/build.gradle

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ dependencies {
2121

2222
// This dependency is used by the application.
2323
implementation libs.guava
24+
25+
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'
26+
27+
implementation 'org.bouncycastle:bcprov-lts8on:2.73.6'
28+
2429
}
2530

2631
// Apply a specific Java toolchain to ease working on different environments.
@@ -32,5 +37,5 @@ java {
3237

3338
application {
3439
// Define the main class for the application.
35-
mainClass = 'org.example.App'
40+
mainClass = 'com.github.gyk4j.wsgup.App'
3641
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package com.github.gyk4j.wsgup;
2+
3+
import java.io.File;
4+
import java.io.FileNotFoundException;
5+
import java.io.IOException;
6+
7+
import java.nio.charset.Charset;
8+
import java.nio.charset.StandardCharsets;
9+
import java.time.LocalDate;
10+
import java.time.format.DateTimeFormatter;
11+
12+
import java.security.Security;
13+
import java.security.Key;
14+
import java.security.InvalidKeyException;
15+
import java.security.InvalidAlgorithmParameterException;
16+
import java.security.NoSuchAlgorithmException;
17+
import java.security.NoSuchProviderException;
18+
import javax.crypto.Cipher;
19+
import javax.crypto.spec.SecretKeySpec;
20+
import javax.crypto.spec.GCMParameterSpec;
21+
import javax.crypto.spec.IvParameterSpec;
22+
import javax.crypto.IllegalBlockSizeException;
23+
import javax.crypto.NoSuchPaddingException;
24+
import javax.crypto.BadPaddingException;
25+
26+
import com.fasterxml.jackson.core.JsonProcessingException;
27+
import com.fasterxml.jackson.databind.JsonNode;
28+
import com.fasterxml.jackson.databind.ObjectMapper;
29+
30+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
31+
import org.bouncycastle.util.encoders.Hex;
32+
33+
public class App {
34+
35+
public static final String BOUNCY_CASTLE = "BC";
36+
37+
public static final String ALGORITHM = "AES";
38+
public static final String MODE = "CCM";
39+
public static final String PADDING = "NoPadding";
40+
41+
public static final int TAG_LENGTH = 16;
42+
public static final int NONCE_LENGTH = 12;
43+
44+
public static final Charset ENCODING_UTF8 = StandardCharsets.UTF_8;
45+
46+
public static void main(String[] args) {
47+
try {
48+
File register = new File("../../../shared/register.json");
49+
ObjectMapper mapper = new ObjectMapper();
50+
JsonNode registration = mapper.readTree(register);
51+
52+
JsonNode date = registration.get("date");
53+
/*
54+
System.out.format("Date : %02d-%02d-%04d%n",
55+
date.get("day").asInt(),
56+
date.get("month").asInt(),
57+
date.get("year").asInt());
58+
59+
System.out.format("OTP : %06d%n", registration.get("otp").asInt());
60+
System.out.format("TransID: %s%n", registration.get("transid").asText());
61+
*/
62+
63+
// Read test data from file
64+
File testData = new File("../../../shared/testdata.json");
65+
66+
// Parse JSON test data
67+
JsonNode res = mapper.readTree(testData);
68+
69+
JsonNode body = res.get("body");
70+
71+
/*
72+
System.out.format("iv = %s%n", body.get("iv").asText());
73+
System.out.format("enc_userid = %s%n", body.get("enc_userid").asText());
74+
System.out.format("tag_userid = %s%n", body.get("tag_userid").asText());
75+
System.out.format("userid = %s%n", body.get("userid").asText());
76+
System.out.format("enc_password = %s%n", body.get("enc_password").asText());
77+
System.out.format("tag_password = %s%n", body.get("tag_password").asText());
78+
*/
79+
80+
// Build the decryption key
81+
/*
82+
LocalDate today = LocalDate.now();
83+
*/
84+
85+
LocalDate today = LocalDate.of(
86+
date.get("year").asInt(),
87+
date.get("month").asInt(),
88+
date.get("day").asInt());
89+
90+
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("dMM");
91+
String dateStr = today.format(pattern);
92+
String dateHex = String.format("%03x", Integer.parseInt(dateStr));
93+
94+
int otp = registration.get("otp").asInt();
95+
String otpHex = String.format("%05x", otp);
96+
String transId = registration.get("transid").asText();
97+
String keyHex = dateHex + transId + otpHex;
98+
99+
byte[] key = Hex.decode(keyHex);
100+
101+
// Prepare to decrypt user ID and password
102+
Security.addProvider(new BouncyCastleProvider());
103+
Key secretKey = new SecretKeySpec(key, ALGORITHM);
104+
105+
byte[] nonce = body.get("iv").asText().getBytes(ENCODING_UTF8);
106+
GCMParameterSpec iv = new GCMParameterSpec(TAG_LENGTH*8, nonce);
107+
108+
Cipher cipher = Cipher.getInstance(
109+
ALGORITHM + "/" + MODE + "/" + PADDING,
110+
BOUNCY_CASTLE);
111+
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
112+
113+
// Decrypt user ID
114+
String encUserId = body.get("enc_userid").asText();
115+
String tagUserId = body.get("tag_userid").asText();
116+
String userIdTagHex = encUserId + tagUserId;
117+
byte[] userIdTagBin = Hex.decode(userIdTagHex);
118+
119+
String userId = new String(
120+
cipher.doFinal(userIdTagBin),
121+
ENCODING_UTF8);
122+
123+
System.out.format("User ID = %s%n", userId);
124+
125+
// Decrypt password
126+
String encPassword = body.get("enc_password").asText();
127+
String tagPassword = body.get("tag_password").asText();
128+
String passwordTagHex = encPassword + tagPassword;
129+
byte[] passwordTagBin = Hex.decode(passwordTagHex);
130+
131+
String password = new String(
132+
cipher.doFinal(passwordTagBin),
133+
ENCODING_UTF8);
134+
135+
System.out.format("Password = %s%n", password);
136+
137+
} catch(FileNotFoundException ex) {
138+
ex.printStackTrace();
139+
} catch(IOException ex) {
140+
ex.printStackTrace();
141+
} catch(NoSuchAlgorithmException ex) {
142+
ex.printStackTrace();
143+
} catch(NoSuchProviderException ex) {
144+
ex.printStackTrace();
145+
} catch(InvalidKeyException ex) {
146+
ex.printStackTrace();
147+
} catch(IllegalBlockSizeException ex) {
148+
ex.printStackTrace();
149+
} catch(NoSuchPaddingException ex) {
150+
ex.printStackTrace();
151+
} catch(InvalidAlgorithmParameterException ex) {
152+
ex.printStackTrace();
153+
} catch(BadPaddingException ex) {
154+
ex.printStackTrace();
155+
}
156+
}
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module wsgup {
2+
requires org.bouncycastle.lts.prov;
3+
requires com.fasterxml.jackson.databind;
4+
}

java/wsgup/app/src/main/java/org/example/App.java

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
/*
2-
* This source file was generated by the Gradle 'init' task
3-
*/
4-
package org.example;
1+
package com.github.gyk4j.wsgup;
52

63
import org.junit.Test;
74
import static org.junit.Assert.*;
8-
5+
/*
96
public class AppTest {
7+
108
@Test public void appHasAGreeting() {
119
App classUnderTest = new App();
1210
assertNotNull("app should have a greeting", classUnderTest.getGreeting());
1311
}
12+
1413
}
14+
*/

0 commit comments

Comments
 (0)