Skip to content

Commit d198c04

Browse files
author
chengyitian
committed
Merge branch 'master' of dolphindb.net:dolphindb/api-java into dev
# Conflicts: # src/com/xxdb/DBConnection.java
2 parents ec88bbf + 4ec4bb1 commit d198c04

15 files changed

+895
-34
lines changed

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>com.dolphindb</groupId>
44
<artifactId>dolphindb-javaapi</artifactId>
5-
<version>3.00.2.4</version>
5+
<version>3.00.2.5</version>
66
<packaging>jar</packaging>
77

88
<properties>
9-
<dolphindb.version>3.00.2.4</dolphindb.version>
9+
<dolphindb.version>3.00.2.5</dolphindb.version>
1010
</properties>
1111
<name>DolphinDB Java API</name>
1212
<description>The messaging and data conversion protocol between Java and DolphinDB server</description>
@@ -31,7 +31,7 @@
3131
<connection>scm:git:git@github.com:dolphindb/api-java.git</connection>
3232
<developerConnection>scm:git:git@github.com:dolphindb/api-java.git</developerConnection>
3333
<url>git@github.com:dolphindb/api-java.git</url>
34-
<tag>api-java-3.00.2.4</tag>
34+
<tag>api-java-3.00.2.5</tag>
3535
</scm>
3636
<dependencies>
3737
<dependency>

src/com/xxdb/CryptoUtils.java

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
package com.xxdb;
2+
3+
import javax.crypto.Mac;
4+
import javax.crypto.SecretKeyFactory;
5+
import javax.crypto.spec.PBEKeySpec;
6+
import javax.crypto.spec.SecretKeySpec;
7+
import java.nio.charset.StandardCharsets;
8+
import java.security.InvalidKeyException;
9+
import java.security.MessageDigest;
10+
import java.security.NoSuchAlgorithmException;
11+
import java.security.SecureRandom;
12+
import java.security.spec.InvalidKeySpecException;
13+
import java.util.Base64;
14+
15+
public class CryptoUtils {
16+
17+
private static final SecureRandom secureRandom = new SecureRandom();
18+
19+
private static final int SHA256_DIGEST_LENGTH = 32; // 256 bits = 32 bytes
20+
21+
public static String base64Encode(byte[] text, boolean noNewLines) {
22+
Base64.Encoder encoder;
23+
24+
if (noNewLines) {
25+
// Use encoder without line breaks
26+
encoder = Base64.getEncoder().withoutPadding();
27+
} else {
28+
// Use standard encoder
29+
encoder = Base64.getEncoder();
30+
}
31+
32+
return encoder.encodeToString(text);
33+
}
34+
35+
public static byte[] base64Decode(String input, boolean noNewLines) {
36+
if (input == null)
37+
throw new IllegalArgumentException("Input string cannot be null");
38+
39+
Base64.Decoder decoder;
40+
41+
if (noNewLines) {
42+
// Use standard decoder (doesn't handle line breaks)
43+
decoder = Base64.getDecoder();
44+
} else {
45+
// Use MIME decoder (handles line breaks)
46+
decoder = Base64.getMimeDecoder();
47+
}
48+
49+
return decoder.decode(input);
50+
}
51+
52+
public static String generateNonce(int length) {
53+
// Generate random byte array
54+
byte[] buffer = new byte[length];
55+
secureRandom.nextBytes(buffer);
56+
57+
// Base64 encode without line breaks
58+
return Base64.getEncoder().encodeToString(buffer);
59+
}
60+
61+
public static byte[] pbkdf2HmacSha256(String password, byte[] salt, int iterCount) {
62+
try {
63+
// Create PBEKeySpec
64+
PBEKeySpec spec = new PBEKeySpec(
65+
password.toCharArray(),
66+
salt,
67+
iterCount,
68+
SHA256_DIGEST_LENGTH * 8 // Convert to bits
69+
);
70+
71+
// Get PBKDF2WithHmacSHA256 instance
72+
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
73+
74+
// Generate key
75+
byte[] saltedPassword = factory.generateSecret(spec).getEncoded();
76+
77+
// Clear sensitive data
78+
spec.clearPassword();
79+
80+
return saltedPassword;
81+
82+
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
83+
throw new RuntimeException("Failed to compute PBKDF2-HMAC-SHA256: " + e.getMessage(), e);
84+
}
85+
}
86+
87+
/**
88+
* Calculate client key
89+
* @param saltedPassword Password processed with PBKDF2
90+
* @return Client key
91+
*/
92+
public static byte[] computeClientKey(byte[] saltedPassword) {
93+
if (saltedPassword == null || saltedPassword.length != SHA256_DIGEST_LENGTH) {
94+
throw new IllegalArgumentException("Invalid salted password");
95+
}
96+
97+
// Byte array for "Client Key"
98+
byte[] clientKeyData = "Client Key".getBytes();
99+
100+
// Calculate HMAC
101+
return hmacSha256(saltedPassword, clientKeyData);
102+
}
103+
104+
/**
105+
* Calculate stored key (SHA-256 hash of client key)
106+
* @param clientKey Client key
107+
* @return Stored key
108+
*/
109+
public static byte[] computeStoredKey(byte[] clientKey) {
110+
if (clientKey == null || clientKey.length != SHA256_DIGEST_LENGTH) {
111+
throw new IllegalArgumentException("Invalid client key");
112+
}
113+
114+
return sha256(clientKey);
115+
}
116+
117+
/**
118+
* Calculate client signature
119+
* @param storedKey Stored key
120+
* @param authMessage Authentication message
121+
* @return Client signature
122+
*/
123+
public static byte[] computeClientSignature(byte[] storedKey, String authMessage) {
124+
if (storedKey == null || storedKey.length != SHA256_DIGEST_LENGTH) {
125+
throw new IllegalArgumentException("Invalid stored key");
126+
}
127+
if (authMessage == null) {
128+
throw new IllegalArgumentException("Auth message cannot be null");
129+
}
130+
131+
try {
132+
// Create HMAC-SHA256 instance
133+
Mac hmac = Mac.getInstance("HmacSHA256");
134+
135+
// Initialize key
136+
SecretKeySpec secretKey = new SecretKeySpec(storedKey, "HmacSHA256");
137+
hmac.init(secretKey);
138+
139+
// Calculate HMAC
140+
return hmac.doFinal(authMessage.getBytes());
141+
142+
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
143+
throw new RuntimeException("Failed to compute client signature: " + e.getMessage(), e);
144+
}
145+
}
146+
147+
/**
148+
* Calculate proof (XOR operation between client key and client signature)
149+
* @param clientKey Client key
150+
* @param clientSignature Client signature
151+
* @return Proof result
152+
*/
153+
public static byte[] computeProof(byte[] clientKey, byte[] clientSignature) {
154+
if (clientKey == null || clientSignature == null ||
155+
clientKey.length != clientSignature.length) {
156+
throw new IllegalArgumentException("Invalid input arrays");
157+
}
158+
159+
byte[] proof = new byte[clientKey.length];
160+
for (int i = 0; i < clientKey.length; i++) {
161+
proof[i] = (byte)(clientKey[i] ^ clientSignature[i]);
162+
}
163+
return proof;
164+
}
165+
166+
/**
167+
* Calculate server key
168+
* @param saltedPassword Password processed with PBKDF2
169+
* @return Server key
170+
*/
171+
public static byte[] computeServerKey(byte[] saltedPassword) {
172+
if (saltedPassword == null || saltedPassword.length != SHA256_DIGEST_LENGTH) {
173+
throw new IllegalArgumentException("Invalid salted password");
174+
}
175+
176+
try {
177+
// Create HMAC-SHA256 instance
178+
Mac hmac = Mac.getInstance("HmacSHA256");
179+
180+
// Initialize key
181+
SecretKeySpec secretKey = new SecretKeySpec(saltedPassword, "HmacSHA256");
182+
hmac.init(secretKey);
183+
184+
// Calculate HMAC
185+
return hmac.doFinal("Server Key".getBytes(StandardCharsets.UTF_8));
186+
187+
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
188+
throw new RuntimeException("Failed to compute server key: " + e.getMessage(), e);
189+
}
190+
}
191+
192+
/**
193+
* Calculate server signature
194+
* @param serverKey Server key
195+
* @param authMessage Authentication message
196+
* @return Server signature
197+
*/
198+
public static byte[] computeServerSignature(byte[] serverKey, String authMessage) {
199+
if (serverKey == null || serverKey.length != SHA256_DIGEST_LENGTH) {
200+
throw new IllegalArgumentException("Invalid server key");
201+
}
202+
if (authMessage == null) {
203+
throw new IllegalArgumentException("Auth message cannot be null");
204+
}
205+
206+
try {
207+
// Create HMAC-SHA256 instance
208+
Mac hmac = Mac.getInstance("HmacSHA256");
209+
210+
// Initialize key
211+
SecretKeySpec secretKey = new SecretKeySpec(serverKey, "HmacSHA256");
212+
hmac.init(secretKey);
213+
214+
// Calculate HMAC
215+
return hmac.doFinal(authMessage.getBytes(StandardCharsets.UTF_8));
216+
217+
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
218+
throw new RuntimeException("Failed to compute server signature: " + e.getMessage(), e);
219+
}
220+
}
221+
222+
223+
224+
/**
225+
* Calculate HMAC-SHA256
226+
* @param key HMAC key
227+
* @param data Data to calculate HMAC for
228+
* @return HMAC result
229+
*/
230+
public static byte[] hmacSha256(byte[] key, byte[] data) {
231+
try {
232+
// Create HMAC-SHA256 instance
233+
Mac hmac = Mac.getInstance("HmacSHA256");
234+
235+
// Initialize key
236+
SecretKeySpec secretKey = new SecretKeySpec(key, "HmacSHA256");
237+
hmac.init(secretKey);
238+
239+
// Calculate HMAC
240+
return hmac.doFinal(data);
241+
242+
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
243+
throw new RuntimeException("Failed to compute HMAC-SHA256: " + e.getMessage(), e);
244+
}
245+
}
246+
247+
/**
248+
* Calculate SHA-256 hash
249+
* @param data Data to hash
250+
* @return Hash result
251+
*/
252+
public static byte[] sha256(byte[] data) {
253+
try {
254+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
255+
return digest.digest(data);
256+
} catch (NoSuchAlgorithmException e) {
257+
throw new RuntimeException("SHA-256 algorithm not available", e);
258+
}
259+
}
260+
}

0 commit comments

Comments
 (0)