SHA256
27 03 25
Доделал сервер и документ для разработчиков по Авторификациии и серверам Всё работает
This commit is contained in:
@@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* - и после завершения оставить в БД 3 активных сессии (S1,S2,S3)
|
||||
*
|
||||
* Протокол v2:
|
||||
* - создание сессии: AuthChallenge -> CreateAuthSession (deviceKey подпись, + sessionPubKey)
|
||||
* - создание сессии: AuthChallenge -> CreateAuthSession (deviceKey подпись, + deviceKey + sessionKey)
|
||||
* - вход в сессию: SessionChallenge(sessionId) -> nonce, затем SessionLogin(sessionId,time,signature(sessionKey))
|
||||
* - ListSessions и CloseActiveSession доступны только в AUTH_STATUS_USER (после SessionLogin)
|
||||
*/
|
||||
@@ -109,16 +109,15 @@ public class IT_02_Sessions {
|
||||
String authNonce = JsonParsers.authNonce(nonceResp);
|
||||
assertNotNull(authNonce, "authNonce must not be null for " + label);
|
||||
|
||||
// для тестов: sessionKey = deviceKey (в реале будет отдельный keypair)
|
||||
String sessionPubKeyB64 = TestConfig.devicePublicKeyB64(login);
|
||||
String sessionKey = TestConfig.sessionKey(login);
|
||||
|
||||
// storagePwd на клиенте (сохраняем, чтобы потом проверить, что сервер вернул именно его)
|
||||
String storagePwd = TestConfig.fakeStoragePwd();
|
||||
|
||||
// шаг 2: CreateAuthSession (device подпись + sessionPubKey)
|
||||
// шаг 2: CreateAuthSession (device подпись + deviceKey + sessionKey)
|
||||
String createResp = ws.call(
|
||||
"CreateAuthSession(" + label + ")",
|
||||
JsonBuilders.createAuthSessionV2(login, authNonce, storagePwd, sessionPubKeyB64),
|
||||
JsonBuilders.createAuthSessionV2(login, authNonce, storagePwd, sessionKey),
|
||||
t
|
||||
);
|
||||
assertEquals(200, JsonParsers.status(createResp), "CreateAuthSession(" + label + ") must be 200");
|
||||
@@ -128,10 +127,9 @@ public class IT_02_Sessions {
|
||||
|
||||
r.ok("Создана сессия " + label + ": sessionId=" + sid);
|
||||
|
||||
// для тестов используем devicePriv как sessionPriv
|
||||
byte[] sessionPrivKey = TestConfig.getDevicePrivatKey(login);
|
||||
byte[] sessionPrivKey = TestConfig.getSessionPrivatKey(login);
|
||||
|
||||
return new Session(sid, sessionPrivKey, storagePwd);
|
||||
return new Session(sid, sessionKey, sessionPrivKey, storagePwd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +141,7 @@ public class IT_02_Sessions {
|
||||
assertNotNull(nonce, "SessionChallenge nonce must not be null");
|
||||
|
||||
// шаг 2: SessionLogin(sessionId, timeMs, signature(sessionKey, SESSION_LOGIN:...))
|
||||
String loginResp = ws.call("SessionLogin " + label, JsonBuilders.sessionLogin(s.sessionId, nonce, s.sessionPrivKey), t);
|
||||
String loginResp = ws.call("SessionLogin " + label, JsonBuilders.sessionLogin(s.sessionId, s.sessionKey, nonce, s.sessionPrivKey), t);
|
||||
assertEquals(200, JsonParsers.status(loginResp), "SessionLogin must be 200");
|
||||
|
||||
String storagePwd = JsonParsers.storagePwd(loginResp);
|
||||
@@ -153,5 +151,5 @@ public class IT_02_Sessions {
|
||||
r.ok(label + ": SessionLogin OK, storagePwd verified");
|
||||
}
|
||||
|
||||
private record Session(String sessionId, byte[] sessionPrivKey, String storagePwd) {}
|
||||
}
|
||||
private record Session(String sessionId, String sessionKey, byte[] sessionPrivKey, String storagePwd) {}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ public final class TestConfig {
|
||||
|
||||
// NEW: session pub b64 helper
|
||||
public static String sessionPublicKeyB64(String login) { return Base64.getEncoder().encodeToString(getSessionPublicKey(login)); }
|
||||
public static String sessionKey(String login) { return "ed25519/" + sessionPublicKeyB64(login); }
|
||||
|
||||
// ============ backward-compatible helpers for "user1" ============
|
||||
public static String BCH_NAME() { return getBlockchainName(LOGIN()); }
|
||||
@@ -143,6 +144,9 @@ public final class TestConfig {
|
||||
public static String SESSION_PUBKEY_B64() { return sessionPublicKeyB64(LOGIN()); }
|
||||
public static String SESSION2_PUBKEY_B64() { return sessionPublicKeyB64(LOGIN2()); }
|
||||
public static String SESSION3_PUBKEY_B64() { return sessionPublicKeyB64(LOGIN3()); }
|
||||
public static String SESSION_KEY() { return sessionKey(LOGIN()); }
|
||||
public static String SESSION2_KEY() { return sessionKey(LOGIN2()); }
|
||||
public static String SESSION3_KEY() { return sessionKey(LOGIN3()); }
|
||||
|
||||
// ============ misc ============
|
||||
public static String fakeStoragePwd() {
|
||||
@@ -154,4 +158,4 @@ public final class TestConfig {
|
||||
if (v == null) throw new IllegalStateException("No key in " + mapName + " for login=" + login);
|
||||
return v.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,20 +104,15 @@ public final class JsonBuilders {
|
||||
}
|
||||
|
||||
// ---------------- CreateAuthSession (v2) ----------------
|
||||
// v2: sessionKey генерируется/хранится на клиенте, на сервер отправляем sessionPubKeyB64 (base64).
|
||||
//
|
||||
// ВАЖНО (новое правило):
|
||||
// Подпись CreateAuthSession делается ТОЛЬКО deviceKey над строкой:
|
||||
// preimage = "AUTH_CREATE_SESSION:" + login + ":" + timeMs + ":" + authNonce
|
||||
//
|
||||
// storagePwd и sessionPubKeyB64 НЕ входят в preimage.
|
||||
// Подпись CreateAuthSession делается deviceKey над строкой:
|
||||
// preimage = "AUTH_CREATE_SESSION:" + login + ":" + sessionKey + ":" + storagePwd + ":" + timeMs + ":" + authNonce
|
||||
|
||||
public static String createAuthSessionV2(String login, String authNonce, String storagePwd, String sessionPubKeyB64) {
|
||||
public static String createAuthSessionV2(String login, String authNonce, String storagePwd, String sessionKey) {
|
||||
long timeMs = System.currentTimeMillis();
|
||||
|
||||
// подпись делаем devicePrivKey
|
||||
byte[] devicePriv = TestConfig.getDevicePrivatKey(login);
|
||||
String sigB64 = signAuthCreateSession(login, timeMs, authNonce, devicePriv);
|
||||
String deviceKey = TestConfig.devicePublicKeyB64(login);
|
||||
String sigB64 = signAuthCreateSession(login, sessionKey, storagePwd, timeMs, authNonce, devicePriv);
|
||||
|
||||
String requestId = TestIds.next("create");
|
||||
return """
|
||||
@@ -125,18 +120,24 @@ public final class JsonBuilders {
|
||||
"op": "CreateAuthSession",
|
||||
"requestId": "%s",
|
||||
"payload": {
|
||||
"login": "%s",
|
||||
"storagePwd": "%s",
|
||||
"sessionPubKeyB64": "%s",
|
||||
"sessionKey": "%s",
|
||||
"timeMs": %d,
|
||||
"authNonce": "%s",
|
||||
"deviceKey": "%s",
|
||||
"signatureB64": "%s",
|
||||
"clientInfo": "%s"
|
||||
}
|
||||
}
|
||||
""".formatted(
|
||||
requestId,
|
||||
login,
|
||||
storagePwd,
|
||||
sessionPubKeyB64,
|
||||
sessionKey,
|
||||
timeMs,
|
||||
authNonce,
|
||||
deviceKey,
|
||||
sigB64,
|
||||
TestConfig.TEST_CLIENT_INFO
|
||||
);
|
||||
@@ -161,7 +162,7 @@ public final class JsonBuilders {
|
||||
// Подпись SessionLogin по-прежнему делается sessionPrivKey:
|
||||
// preimage = "SESSION_LOGIN:" + sessionId + ":" + timeMs + ":" + nonce
|
||||
|
||||
public static String sessionLogin(String sessionId, String nonce, byte[] sessionPrivKey) {
|
||||
public static String sessionLogin(String sessionId, String sessionKey, String nonce, byte[] sessionPrivKey) {
|
||||
long timeMs = System.currentTimeMillis();
|
||||
String sigB64 = signSessionLogin(sessionId, timeMs, nonce, sessionPrivKey);
|
||||
|
||||
@@ -172,12 +173,13 @@ public final class JsonBuilders {
|
||||
"requestId": "%s",
|
||||
"payload": {
|
||||
"sessionId": "%s",
|
||||
"sessionKey": "%s",
|
||||
"timeMs": %d,
|
||||
"signatureB64": "%s",
|
||||
"clientInfo": "%s"
|
||||
}
|
||||
}
|
||||
""".formatted(requestId, sessionId, timeMs, sigB64, TestConfig.TEST_CLIENT_INFO);
|
||||
""".formatted(requestId, sessionId, sessionKey, timeMs, sigB64, TestConfig.TEST_CLIENT_INFO);
|
||||
}
|
||||
|
||||
// ---------------- ListSessions ----------------
|
||||
@@ -226,11 +228,11 @@ public final class JsonBuilders {
|
||||
|
||||
/**
|
||||
* Подпись CreateAuthSession(v2):
|
||||
* preimage = "AUTH_CREATE_SESSION:" + login + ":" + timeMs + ":" + authNonce
|
||||
* preimage = "AUTH_CREATE_SESSION:" + login + ":" + sessionKey + ":" + storagePwd + ":" + timeMs + ":" + authNonce
|
||||
* подписываем devicePrivKey.
|
||||
*/
|
||||
public static String signAuthCreateSession(String login, long timeMs, String authNonce, byte[] devicePrivKey) {
|
||||
String preimageStr = "AUTH_CREATE_SESSION:" + login + ":" + timeMs + ":" + authNonce;
|
||||
public static String signAuthCreateSession(String login, String sessionKey, String storagePwd, long timeMs, String authNonce, byte[] devicePrivKey) {
|
||||
String preimageStr = "AUTH_CREATE_SESSION:" + login + ":" + sessionKey + ":" + storagePwd + ":" + timeMs + ":" + authNonce;
|
||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] sig = Ed25519Util.sign(preimage, devicePrivKey);
|
||||
return Base64.getEncoder().encodeToString(sig);
|
||||
@@ -247,4 +249,4 @@ public final class JsonBuilders {
|
||||
byte[] sig = Ed25519Util.sign(preimage, sessionPrivKey);
|
||||
return Base64.getEncoder().encodeToString(sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user