вынес константы SHiNe
This commit is contained in:
AidarKC 2026-01-08 00:02:43 +03:00
parent 1c94bb25a6
commit f1af2bd4d4
4 changed files with 47 additions and 20 deletions

View File

@ -26,6 +26,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0'
implementation project(':shine-server-config') // модуль с настройками
implementation project(":shine-server-log") // модуль логирования и уведомления админов implementation project(":shine-server-log") // модуль логирования и уведомления админов
implementation project(':shine-server-db') // модуль для работы с БД содержит и сущности из БД и саму работу с БД implementation project(':shine-server-db') // модуль для работы с БД содержит и сущности из БД и саму работу с БД

View File

@ -1,5 +1,6 @@
package blockchain; package blockchain;
import utils.config.ShineSignatureConstants;
import utils.crypto.Ed25519Util; import utils.crypto.Ed25519Util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -10,13 +11,16 @@ import java.util.Objects;
public final class BchCryptoVerifier { public final class BchCryptoVerifier {
private static final byte[] DOMAIN = "SHiNE".getBytes(StandardCharsets.US_ASCII);
private BchCryptoVerifier() {} private BchCryptoVerifier() {}
// строка из констант; байты/длина локально, на месте
private static final String DOMAIN_STR = ShineSignatureConstants.BLOCK_HASH_DOMAIN;
private static final byte[] DOMAIN = DOMAIN_STR.getBytes(StandardCharsets.US_ASCII);
private static final int DOMAIN_LEN = DOMAIN.length;
/** /**
* preimage = * preimage =
* "SHiNE" + * DOMAIN +
* [1] loginLen + loginBytes + * [1] loginLen + loginBytes +
* prevGlobalHash32 + * prevGlobalHash32 +
* prevLineHash32 + * prevLineHash32 +
@ -40,7 +44,7 @@ public final class BchCryptoVerifier {
throw new IllegalArgumentException("login >255 bytes"); throw new IllegalArgumentException("login >255 bytes");
ByteBuffer bb = ByteBuffer.allocate( ByteBuffer bb = ByteBuffer.allocate(
DOMAIN.length + DOMAIN_LEN +
1 + loginBytes.length + 1 + loginBytes.length +
32 + 32 + 32 + 32 +
rawBytes.length rawBytes.length

View File

@ -1,6 +1,7 @@
package blockchain.body; package blockchain.body;
import blockchain.LineIndex; import blockchain.LineIndex;
import utils.config.ShineSignatureConstants;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
@ -15,10 +16,8 @@ import java.util.Objects;
* [2] version=1 * [2] version=1
* *
* [2] subType (uint16) = 0 * [2] subType (uint16) = 0
* (служебное поле для совместимости с единым форматом body,
* чтобы ВСЕ body имели subType одинаковым способом)
* *
* [5] tag ASCII "SHiNE" * [TAG_LEN] tag ASCII "SHiNE"
* [1] loginLength=N (uint8) * [1] loginLength=N (uint8)
* [N] login UTF-8 * [N] login UTF-8
* *
@ -35,7 +34,12 @@ public final class HeaderBody implements BodyRecord {
/** Для header всегда 0 (служебная совместимость). */ /** Для header всегда 0 (служебная совместимость). */
public static final short SUBTYPE_COMPAT = 0; public static final short SUBTYPE_COMPAT = 0;
public static final String TAG = "SHiNE"; /** TAG формата (ASCII). Значение берём из общих строковых констант. */
public static final String TAG = ShineSignatureConstants.BLOCKCHAIN_HEADER_TAG;
// производные значения считаем "на месте", а не в константах
private static final byte[] TAG_ASCII = TAG.getBytes(StandardCharsets.US_ASCII);
private static final int TAG_LEN = TAG_ASCII.length;
public final short subType; // всегда 0 public final short subType; // всегда 0
public final String tag; // "SHiNE" public final String tag; // "SHiNE"
@ -57,11 +61,11 @@ public final class HeaderBody implements BodyRecord {
if (this.subType != SUBTYPE_COMPAT) if (this.subType != SUBTYPE_COMPAT)
throw new IllegalArgumentException("HeaderBody subType must be 0, got=" + (this.subType & 0xFFFF)); throw new IllegalArgumentException("HeaderBody subType must be 0, got=" + (this.subType & 0xFFFF));
// дальше: tag[5] + loginLen[1] минимум // дальше: tag[TAG_LEN] + loginLen[1] минимум
if (bb.remaining() < 5 + 1) if (bb.remaining() < TAG_LEN + 1)
throw new IllegalArgumentException("Header payload too short"); throw new IllegalArgumentException("Header payload too short");
byte[] tagBytes = new byte[5]; byte[] tagBytes = new byte[TAG_LEN];
bb.get(tagBytes); bb.get(tagBytes);
String t = new String(tagBytes, StandardCharsets.US_ASCII); String t = new String(tagBytes, StandardCharsets.US_ASCII);
if (!TAG.equals(t)) throw new IllegalArgumentException("Bad tag: " + t); if (!TAG.equals(t)) throw new IllegalArgumentException("Bad tag: " + t);
@ -75,7 +79,6 @@ public final class HeaderBody implements BodyRecord {
bb.get(loginBytes); bb.get(loginBytes);
this.login = new String(loginBytes, StandardCharsets.UTF_8); this.login = new String(loginBytes, StandardCharsets.UTF_8);
// запрещаем мусор в конце
if (bb.remaining() != 0) { if (bb.remaining() != 0) {
throw new IllegalArgumentException("Unexpected tail bytes, remaining=" + bb.remaining()); throw new IllegalArgumentException("Unexpected tail bytes, remaining=" + bb.remaining());
} }
@ -95,7 +98,8 @@ public final class HeaderBody implements BodyRecord {
@Override @Override
public short expectedLineIndex() { public short expectedLineIndex() {
return LineIndex.HEADER; } return LineIndex.HEADER;
}
@Override @Override
public HeaderBody check() { public HeaderBody check() {
@ -115,8 +119,8 @@ public final class HeaderBody implements BodyRecord {
if (loginUtf8.length > 255) if (loginUtf8.length > 255)
throw new IllegalArgumentException("Login too long (>255 bytes)"); throw new IllegalArgumentException("Login too long (>255 bytes)");
// type[2] + ver[2] + subType[2] + tag[5] + loginLen[1] + login[N] // type[2] + ver[2] + subType[2] + tag[TAG_LEN] + loginLen[1] + login[N]
int cap = 2 + 2 + 2 + 5 + 1 + loginUtf8.length; int cap = 2 + 2 + 2 + TAG_LEN + 1 + loginUtf8.length;
ByteBuffer bb = ByteBuffer.allocate(cap).order(ByteOrder.BIG_ENDIAN); ByteBuffer bb = ByteBuffer.allocate(cap).order(ByteOrder.BIG_ENDIAN);
@ -125,9 +129,9 @@ public final class HeaderBody implements BodyRecord {
bb.putShort(SUBTYPE_COMPAT); bb.putShort(SUBTYPE_COMPAT);
bb.put(TAG.getBytes(StandardCharsets.US_ASCII)); // [5] bb.put(TAG_ASCII); // [TAG_LEN]
bb.put((byte) loginUtf8.length); // [1] bb.put((byte) loginUtf8.length); // [1]
bb.put(loginUtf8); // [N] bb.put(loginUtf8); // [N]
return bb.array(); return bb.array();
} }

View File

@ -1,11 +1,11 @@
package utils.config; package utils.config;
/** /**
* ShineSignatureConstants строковые префиксы, входящие в подписываемые сообщения. * ShineSignatureConstants строковые префиксы/домены, входящие в подписываемые сообщения.
* *
* ВАЖНО: * ВАЖНО:
* - префикс добавляется в начало "чтобы подпись нельзя было переиспользовать" между разными типами сообщений. * - префикс добавляется в начало "чтобы подпись нельзя было переиспользовать" между разными типами сообщений.
* - менять префиксы после релиза нельзя, иначе старые подписи перестанут проверяться. * - менять значения после релиза нельзя, иначе старые подписи перестанут проверяться.
*/ */
public final class ShineSignatureConstants { public final class ShineSignatureConstants {
@ -13,4 +13,22 @@ public final class ShineSignatureConstants {
/** Подписываемые данные параметра пользователя: prefix + login + param + time_ms + value */ /** Подписываемые данные параметра пользователя: prefix + login + param + time_ms + value */
public static final String USER_PARAMETER_PREFIX = "SHiNe/UserParameter:"; public static final String USER_PARAMETER_PREFIX = "SHiNe/UserParameter:";
/** TAG в HeaderBody (genesis). ASCII "SHiNe". */
public static final String BLOCKCHAIN_HEADER_TAG = "SHiNe";
/** DOMAIN для preimage при расчёте hash32 блока. ASCII "SHiNe". */
public static final String BLOCK_HASH_DOMAIN = "SHiNe";
// ===================== Фиксированные размеры =====================
/** Длина SHA-256 хэша, который хранится в блоке. */
public static final int HASH32_LEN = 32;
/** Длина подписи Ed25519, которая хранится в блоке. */
public static final int SIGNATURE64_LEN = 64;
/** Длина публичного ключа Ed25519. */
public static final int ED25519_PUBLIC_KEY32_LEN = 32;
} }