fix(signup): prestore client SID→UDID mapping so game_start can decrypt

After /tool/signup the client switches to SID-only headers (no UDID), so
the next request's body can't be decrypted unless the server already
knows the SID's UDID. ShadowverseSessionService now mirrors the client's
Cute/Cryptographer.MakeMd5(viewerId + udid) formula (salt
"r!I@ws8e5i="), and ToolController.Signup prestores the mapping at the
end. Verified against a live signup capture: viewerId=1 +
udid=62747917-93bc-454c-abb4-ef423b3c9317 produces the captured SID
dc4aac79d35fe15dfb6262e0071bb03c.

Note: this only fixes the fresh-signup path. Clients restarting with a
cached viewer_id (which skip /tool/signup entirely) still hit the same
issue — separate follow-up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-28 13:34:05 -04:00
parent 190b50cbaf
commit 6e6c8ee779
3 changed files with 88 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ using SVSim.Database.Repositories.Viewer;
using SVSim.EmulatedEntrypoint.Extensions;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
using SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
using SVSim.EmulatedEntrypoint.Services;
namespace SVSim.EmulatedEntrypoint.Controllers;
@@ -11,11 +12,16 @@ public class ToolController : SVSimController
{
private readonly ILogger<ToolController> _logger;
private readonly IViewerRepository _viewerRepository;
private readonly ShadowverseSessionService _sessionService;
public ToolController(ILogger<ToolController> logger, IViewerRepository viewerRepository)
public ToolController(
ILogger<ToolController> logger,
IViewerRepository viewerRepository,
ShadowverseSessionService sessionService)
{
_logger = logger;
_viewerRepository = viewerRepository;
_sessionService = sessionService;
}
/// <summary>
@@ -43,6 +49,13 @@ public class ToolController : SVSimController
?? await _viewerRepository.RegisterAnonymousViewer(udid);
HttpContext.SetViewer(viewer);
// Pre-store the SID the client will compute and use for its very next request. After
// signup the client switches to SID-only headers (no UDID), so without this mapping the
// translation middleware can't decrypt the next body. Formula mirrors the decompiled
// Cute/Certification.SessionId getter — see ShadowverseSessionService.ComputeClientSessionId.
_sessionService.StoreSessionForViewer(viewer.Id, udid);
_logger.LogInformation("Signup resolved for udid={Udid} → viewer_id={ViewerId}, short_udid={ShortUdid}.",
udid, viewer.Id, viewer.ShortUdid);