From 53d6d251e931670a2f25293ff5edad8a12fddba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Wed, 17 Jun 2026 00:24:06 +0100 Subject: [PATCH] feat(account-management): use new algorithm for pidHMAC --- README.md | 1 + globals/config.go | 1 + .../nintendo_create_account.go | 23 +++++++++++-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 40c3b9c..17bd554 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,4 @@ All configuration options are handled via environment variables | `PN_FRIENDS_CONFIG_HEALTH_CHECK_PORT` | Port for the basic UDP health check server | No | | `PN_FRIENDS_CONFIG_ENABLE_BELLA` | Enables a debug user named "Bella" which is always assigned as your friend | No | | `PN_FRIENDS_CONFIG_MII_DECRYPT_KEY` | AES key used to decrypt 3DS Mii data (as a hex string) | Yes | +| `PN_FRIENDS_CONFIG_PID_HMAC_KEY` | AES key used for the `pidHMAC` field in accounts | Yes | diff --git a/globals/config.go b/globals/config.go index 02dcf7b..4116222 100644 --- a/globals/config.go +++ b/globals/config.go @@ -15,6 +15,7 @@ type config struct { HealthCheckPort uint16 `envconf:"optional"` EnableBella bool `envconf:"optional"` MiiDecryptKey string + PIDHmacKey string } var Config *config = &config{} diff --git a/nex/account-management/nintendo_create_account.go b/nex/account-management/nintendo_create_account.go index e74784f..ad53625 100644 --- a/nex/account-management/nintendo_create_account.go +++ b/nex/account-management/nintendo_create_account.go @@ -3,8 +3,7 @@ package nex_account_management import ( "crypto/hmac" "crypto/md5" - "encoding/binary" - "encoding/hex" + "strconv" "github.com/PretendoNetwork/friends/globals" "github.com/PretendoNetwork/friends/utility" @@ -13,6 +12,8 @@ import ( account_management "github.com/PretendoNetwork/nex-protocols-go/v2/account-management" ) +const PIDHmacCharset = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}" + func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32, strPrincipalName types.String, strKey types.String, uiGroups types.UInt32, strEmail types.String, oAuthData types.DataHolder) (*nex.RMCMessage, *nex.Error) { if err != nil { globals.Logger.Error(err.Error()) @@ -26,23 +27,27 @@ func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32, } pid := types.NewPID(uint64(decryptedToken.UserPID)) + pidString := strconv.FormatUint(uint64(pid), 10) - pidByteArray := make([]byte, 4) - binary.LittleEndian.PutUint32(pidByteArray, uint32(pid)) - - mac := hmac.New(md5.New, []byte(strKey)) - _, err = mac.Write(pidByteArray) + mac := hmac.New(md5.New, []byte(globals.Config.PIDHmacKey)) + _, err = mac.Write([]byte(pidString)) if err != nil { globals.Logger.Error(err.Error()) return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, err.Error()) } - pidHmac := types.NewString(hex.EncodeToString(mac.Sum(nil))) + macBytes := mac.Sum(nil) + macEncoded := make([]byte, 8) + for i := range 8 { + macEncoded[i] = PIDHmacCharset[int(macBytes[i]) % len(PIDHmacCharset)] + } + + pidHMAC := types.NewString(string(macEncoded)) rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings()) pid.WriteTo(rmcResponseStream) - pidHmac.WriteTo(rmcResponseStream) + pidHMAC.WriteTo(rmcResponseStream) rmcResponseBody := rmcResponseStream.Bytes()