29 01 25
Зделал всё только на база64 без всяких урл сафе Вроде всё работает тест весь проходит
This commit is contained in:
parent
0b2bee0a3d
commit
b5706d3ed5
20
shine-server-net-protocol/src/main/java/server/concat_to_file.sh
Executable file
20
shine-server-net-protocol/src/main/java/server/concat_to_file.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
OUTFILE="all_files.txt"
|
||||
|
||||
# очищаем или создаём файл
|
||||
: > "$OUTFILE"
|
||||
|
||||
# собрать только *.java файлы и вывести их содержимое в файл
|
||||
find . -type f -name "*.java" | sort | while read -r f; do
|
||||
cat "$f" >> "$OUTFILE"
|
||||
echo >> "$OUTFILE" # пустая строка-разделитель
|
||||
done
|
||||
|
||||
# скопировать весь файл в буфер обмена (Wayland)
|
||||
wl-copy < "$OUTFILE"
|
||||
|
||||
echo "Готово!"
|
||||
echo "Все .java файлы собраны в $OUTFILE"
|
||||
echo "Содержимое скопировано в буфер обмена (Wayland)"
|
||||
@ -0,0 +1,40 @@
|
||||
package server.logic.ws_protocol;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Единая утилита Base64 для всего WS-протокола.
|
||||
*
|
||||
* ВАЖНО:
|
||||
* - Используем ТОЛЬКО стандартный Base64 (RFC 4648) алфавит: '+' и '/'.
|
||||
* - Без padding '=' (чтобы строки были короче и стабильнее для JSON).
|
||||
* - Декодер при этом спокойно принимает и с '=' и без '='.
|
||||
*/
|
||||
public final class Base64Ws {
|
||||
|
||||
private static final Base64.Encoder ENC = Base64.getEncoder().withoutPadding();
|
||||
private static final Base64.Decoder DEC = Base64.getDecoder();
|
||||
|
||||
private Base64Ws() {}
|
||||
|
||||
public static String encode(byte[] bytes) {
|
||||
if (bytes == null) throw new IllegalArgumentException("bytes == null");
|
||||
return ENC.encodeToString(bytes);
|
||||
}
|
||||
|
||||
public static byte[] decode(String b64) throws IllegalArgumentException {
|
||||
if (b64 == null) throw new IllegalArgumentException("base64 is null");
|
||||
String s = b64.trim();
|
||||
if (s.isEmpty()) throw new IllegalArgumentException("base64 is empty");
|
||||
return DEC.decode(s);
|
||||
}
|
||||
|
||||
public static byte[] decodeLen(String b64, int expectedLen, String fieldName) throws IllegalArgumentException {
|
||||
byte[] v = decode(b64);
|
||||
if (v.length != expectedLen) {
|
||||
String f = (fieldName == null || fieldName.isBlank()) ? "value" : fieldName;
|
||||
throw new IllegalArgumentException(f + " must be " + expectedLen + " bytes, got " + v.length);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth;
|
||||
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
@ -12,7 +13,6 @@ import shine.db.dao.SolanaUsersDAO;
|
||||
import shine.db.entities.SolanaUserEntry;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* AuthChallenge (v2) — шаг 1 создания новой сессии.
|
||||
@ -72,7 +72,7 @@ public class Net_AuthChallenge_Handler implements JsonMessageHandler {
|
||||
|
||||
byte[] buf = new byte[32];
|
||||
RANDOM.nextBytes(buf);
|
||||
String authNonce = Base64.getUrlEncoder().withoutPadding().encodeToString(buf);
|
||||
String authNonce = Base64Ws.encode(buf);
|
||||
|
||||
ctx.setAuthNonce(authNonce);
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
@ -20,10 +20,11 @@ import shine.geo.ClientInfoService;
|
||||
import shine.geo.GeoLookupService;
|
||||
import utils.crypto.Ed25519Util;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* CreateAuthSession (v2) — шаг 2 создания новой сессии (ТОЛЬКО deviceKey).
|
||||
@ -109,7 +110,7 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
// Проверим, что sessionPubKeyB64 декодируется в 32 байта
|
||||
byte[] sessionPubKey32;
|
||||
try {
|
||||
sessionPubKey32 = decodeBase64Any(sessionPubKeyB64);
|
||||
sessionPubKey32 = Base64Ws.decode(sessionPubKeyB64);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@ -291,7 +292,7 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
|
||||
// deviceKey (pub, 32)
|
||||
byte[] publicKey32 = Ed25519Util.keyFromBase64(user.getDeviceKey());
|
||||
byte[] signature64 = decodeBase64Any(signatureB64);
|
||||
byte[] signature64 = Base64Ws.decode(signatureB64);
|
||||
|
||||
String preimageStr = "AUTH_CREATE_SESSION:" + login + ":" + timeMs + ":" + authNonce;
|
||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||
@ -302,19 +303,6 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
private static String generateRandom32B64Url() {
|
||||
byte[] buf = new byte[32];
|
||||
RANDOM.nextBytes(buf);
|
||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(buf);
|
||||
}
|
||||
|
||||
private static byte[] decodeBase64Any(String s) throws IllegalArgumentException {
|
||||
if (s == null) throw new IllegalArgumentException("base64 is null");
|
||||
String x = s.trim();
|
||||
if (x.isEmpty()) throw new IllegalArgumentException("base64 is empty");
|
||||
|
||||
// сначала url-safe, потом обычный
|
||||
try {
|
||||
return Base64.getUrlDecoder().decode(x);
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
return Base64.getDecoder().decode(x);
|
||||
}
|
||||
return Base64Ws.encode(buf);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth;
|
||||
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
@ -13,7 +14,6 @@ import shine.db.entities.ActiveSessionEntry;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* SessionChallenge (v2) — шаг 1 входа в существующую сессию.
|
||||
@ -70,7 +70,7 @@ public class Net_SessionChallenge_Handler implements JsonMessageHandler {
|
||||
|
||||
byte[] buf = new byte[32];
|
||||
RANDOM.nextBytes(buf);
|
||||
String nonce = Base64.getUrlEncoder().withoutPadding().encodeToString(buf);
|
||||
String nonce = Base64Ws.encode(buf);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
ctx.setSessionLoginNonce(nonce);
|
||||
|
||||
@ -2,6 +2,7 @@ package server.logic.ws_protocol.JSON.handlers.auth;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
@ -21,7 +22,6 @@ import utils.crypto.Ed25519Util;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* SessionLogin (v2) — шаг 2 входа в существующую сессию (по sessionKey).
|
||||
@ -121,7 +121,7 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
);
|
||||
}
|
||||
|
||||
String sessionPubKeyB64 = session.getSessionKey(); // это pubKey
|
||||
String sessionPubKeyB64 = session.getSessionKey(); // это pubKey (Base64(32))
|
||||
if (sessionPubKeyB64 == null || sessionPubKeyB64.isBlank()) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@ -250,20 +250,15 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
String signatureB64
|
||||
) throws IllegalArgumentException {
|
||||
|
||||
// pubKey: Base64(32). (Ed25519Util.keyFromBase64 должен использовать стандартный Base64)
|
||||
byte[] publicKey32 = Ed25519Util.keyFromBase64(sessionPubKeyB64);
|
||||
byte[] signature64 = decodeBase64Any(signatureB64);
|
||||
|
||||
// signature: Base64(64) через единую утилиту WS-протокола
|
||||
byte[] signature64 = Base64Ws.decodeLen(signatureB64, 64, "signatureB64");
|
||||
|
||||
String preimageStr = "SESSION_LOGIN:" + sessionId + ":" + timeMs + ":" + nonce;
|
||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return Ed25519Util.verify(preimage, signature64, publicKey32);
|
||||
}
|
||||
|
||||
private static byte[] decodeBase64Any(String s) throws IllegalArgumentException {
|
||||
try {
|
||||
return Base64.getUrlDecoder().decode(s);
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
return Base64.getDecoder().decode(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
*/
|
||||
public class Net_CreateAuthSession_Request extends Net_Request {
|
||||
|
||||
/** Клиентский пароль для хранения данных (base64url от 32 байт). */
|
||||
/** Клиентский пароль для хранения данных (base64 от 32 байт). */
|
||||
private String storagePwd;
|
||||
|
||||
/** Публичный ключ сессии (sessionPubKey), base64 от 32 байт. */
|
||||
|
||||
@ -14,13 +14,13 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
* "requestId": "...",
|
||||
* "status": 200,
|
||||
* "payload": {
|
||||
* "sessionId": "base64url(32)"
|
||||
* "sessionId": "base64(32)"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public class Net_CreateAuthSession_Response extends Net_Response {
|
||||
|
||||
/** Идентификатор сессии, base64url от 32 байт. */
|
||||
/** Идентификатор сессии, base64 от 32 байт. */
|
||||
private String sessionId;
|
||||
|
||||
public String getSessionId() {
|
||||
|
||||
@ -4,7 +4,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
/**
|
||||
* Ответ на SessionChallenge (v2).
|
||||
* payload: { "nonce": "base64url(32)" }
|
||||
* payload: { "nonce": "base64(32)" }
|
||||
*/
|
||||
public class Net_SessionChallenge_Response extends Net_Response {
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
/**
|
||||
* Ответ на SessionLogin (v2).
|
||||
* payload: { "storagePwd": "base64url(32)" }
|
||||
* payload: { "storagePwd": "base64(32)" }
|
||||
*/
|
||||
public class Net_SessionLogin_Response extends Net_Response {
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import blockchain.body.BodyHasLine;
|
||||
import blockchain.body.BodyHasTarget;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
@ -23,7 +24,6 @@ import shine.db.entities.BlockEntry;
|
||||
import utils.blockchain.BlockchainNameUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
@ -325,7 +325,7 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
|
||||
|
||||
private static byte[] decodeBase64(String b64) {
|
||||
if (b64 == null) throw new IllegalArgumentException("blockBytesB64 == null");
|
||||
return Base64.getDecoder().decode(b64);
|
||||
return Base64Ws.decode(b64);
|
||||
}
|
||||
|
||||
private static long safeAdd(long a, long b) {
|
||||
|
||||
@ -2,6 +2,7 @@ package server.logic.ws_protocol.JSON.handlers.tempToTest;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
@ -19,7 +20,6 @@ import utils.blockchain.BlockchainNameUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
|
||||
public class Net_AddUser_Handler implements JsonMessageHandler {
|
||||
|
||||
@ -62,33 +62,30 @@ public class Net_AddUser_Handler implements JsonMessageHandler {
|
||||
|
||||
try {
|
||||
// базовая валидация форматов ключей: Base64(32 bytes)
|
||||
byte[] solanaKey32 = Base64.getDecoder().decode(req.getSolanaKey());
|
||||
if (solanaKey32.length != 32) {
|
||||
byte[] solanaKey32;
|
||||
byte[] blockchainKey32;
|
||||
byte[] deviceKey32;
|
||||
|
||||
try {
|
||||
solanaKey32 = Base64Ws.decodeLen(req.getSolanaKey(), 32, "solanaKey");
|
||||
blockchainKey32 = Base64Ws.decodeLen(req.getBlockchainKey(), 32, "blockchainKey");
|
||||
deviceKey32 = Base64Ws.decodeLen(req.getDeviceKey(), 32, "deviceKey");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_SOLANA_KEY",
|
||||
"solanaKey должен быть Base64(32 bytes)"
|
||||
"BAD_KEY_FORMAT",
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
byte[] blockchainKey32 = Base64.getDecoder().decode(req.getBlockchainKey());
|
||||
if (blockchainKey32.length != 32) {
|
||||
// (переменные не используются дальше, но оставляем для ясности проверки длины)
|
||||
if (solanaKey32.length != 32 || blockchainKey32.length != 32 || deviceKey32.length != 32) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_BLOCKCHAIN_KEY",
|
||||
"blockchainKey должен быть Base64(32 bytes)"
|
||||
);
|
||||
}
|
||||
|
||||
byte[] deviceKey32 = Base64.getDecoder().decode(req.getDeviceKey());
|
||||
if (deviceKey32.length != 32) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_DEVICE_KEY",
|
||||
"deviceKey должен быть Base64(32 bytes)"
|
||||
"BAD_KEY_FORMAT",
|
||||
"solanaKey/blockchainKey/deviceKey должны быть Base64(32 bytes)"
|
||||
);
|
||||
}
|
||||
|
||||
@ -167,13 +164,6 @@ public class Net_AddUser_Handler implements JsonMessageHandler {
|
||||
|
||||
return resp;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_KEY_FORMAT",
|
||||
e.getMessage()
|
||||
);
|
||||
} catch (SQLException e) {
|
||||
log.error("❌ DB error AddUser", e);
|
||||
return NetExceptionResponseFactory.error(
|
||||
|
||||
@ -2,6 +2,7 @@ package server.logic.ws_protocol.JSON.handlers.userParams;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
@ -21,7 +22,6 @@ import utils.crypto.Ed25519Util;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Net_UpsertUserParam_Handler
|
||||
@ -73,8 +73,8 @@ public class Net_UpsertUserParam_Handler implements JsonMessageHandler {
|
||||
byte[] pubKey32;
|
||||
byte[] sig64;
|
||||
try {
|
||||
pubKey32 = Base64.getDecoder().decode(deviceKeyB64);
|
||||
sig64 = Base64.getDecoder().decode(signatureB64);
|
||||
pubKey32 = Base64Ws.decodeLen(deviceKeyB64, 32, "device_key");
|
||||
sig64 = Base64Ws.decodeLen(signatureB64, 64, "signature");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@ -84,23 +84,6 @@ public class Net_UpsertUserParam_Handler implements JsonMessageHandler {
|
||||
);
|
||||
}
|
||||
|
||||
if (pubKey32.length != 32) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_DEVICE_KEY",
|
||||
"device_key должен быть Base64(32 bytes)"
|
||||
);
|
||||
}
|
||||
if (sig64.length != 64) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_SIGNATURE",
|
||||
"signature должна быть Base64(64 bytes)"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------- Signature verify ----------------
|
||||
String signText = ShineSignatureConstants.USER_PARAMETER_PREFIX
|
||||
+ login
|
||||
|
||||
Loading…
Reference in New Issue
Block a user