Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement]: Make (some) tokens use asymmetric cryptography rather than symmetric cryptography #108

Open
1 task done
jonbarrow opened this issue Aug 9, 2024 · 1 comment
Labels
awaiting-approval Topic has not been approved or denied enhancement An update to an existing part of the codebase

Comments

@jonbarrow
Copy link
Member

jonbarrow commented Aug 9, 2024

Checked Existing

  • I have checked the repository for duplicate issues.

What enhancement would you like to see?

Migrate (some) tokens to using asymmetric cryptography (public/private keys). Years ago we used RSA encryption for tokens, but moved away from it to AES for simplicity and to make the tokens smaller. This is not super great however, since it prevents us from securely allowing 3rd party servers and if the AES keys ever leaked anyone could generate their own.

By using asymmetric cryptography again we can properly issue tokens to individual services, including 3rd parties, with the ability to decrypt the token data without being able to generate any themselves.

Any other details to share? (OPTIONAL)

Not all tokens need to be handled this way. Some tokens, which are always handled internally on the account server, can simply have no meaning whatsoever. Tokens such as access and refresh tokens for example, can likely just be totally random bytes which we lookup the details for (relies on #107)

Nintendo seems to have likely used RSA-1024 for several tokens based on the size of the Wii U NEX token. However a few things should be considered:

  1. It looks like access and refresh tokens do not appear to use RSA. They are very short, hex-encoded, strings which tells me they likely still use AES and/or some randomization? Access keys are always 16 bytes long, which screams AES, but refresh tokens are always 20 bytes long, which screams random? Since these tokens are not used by 3rd parties at all, only within the NNAS server, these can probably stay as AES or even entirely randomized and use [Enhancement]: Store tokens in database #107 to track their data
  2. 3DS tokens from NASC might not be entirely RSA either. They always seem to be 105 bytes long, which could mean they are AES still? The guys from Colors! 3D made mention that they're able to decrypt the tokens to get basic data but then they ask a Nintendo server to verify a token signature, so maybe these use a combination of RSA+AES? Unsure, did not ask and I likely won't Not sure where this info for the key size came from, it's wrong. See the edit below

EDIT:

Here are the details of all tokens officially used by Nintendo on the account server:

  • Access tokens provided by NNAS are always 32 lowercase hex characters (16 bytes)
  • Refresh tokens provided by NNAS are always 40 lowercase hex characters (20 bytes)
  • Service tokens provided by NNAS are always 172 base64 characters (128 bytes)
  • NEX tokens provided by NNAS are always 172 base64 characters (128 bytes)
  • LOGIN tokens from NASC are always 152 base64 characters (112 bytes) using a custom base64 alphabet (+ -> ., / -> -, = -> *)
  • SVCLOC tokens from NASC are always 88 base64 characters (64 bytes) using a custom base64 alphabet (+ -> ., / -> -, = -> *)

This means that, assuming we keep with these same lengths as well, these are our options for keys:

  • Access and refresh tokens should be meaningless random data, used as a lookup internally. Only we use these so that's fine
  • All other tokens should use some compact asymmetric cryptography, like mixing asymmetric with symmetric. ECIES is a good choice here, as ECC can be used to securely create very small encrypted messages/signatures
@jonbarrow jonbarrow added enhancement An update to an existing part of the codebase awaiting-approval Topic has not been approved or denied labels Aug 9, 2024
@jonbarrow jonbarrow changed the title [Enhancement]: Make tokens use RSA again [Enhancement]: Make (some) tokens use RSA again Aug 17, 2024
@jonbarrow jonbarrow changed the title [Enhancement]: Make (some) tokens use RSA again [Enhancement]: Make (some) tokens use asymmetric cryptography rather than symmetric cryptography Aug 17, 2024
@jonbarrow
Copy link
Member Author

jonbarrow commented Sep 3, 2024

I've done some tests with tokens, and these are the results:

  • Access tokens from NNAS will always be capped to 32 characters. Sending anything longer will be truncated to 32 characters
  • Given than access tokens are capped at their official value, we can safely assume refresh tokens from NNAS are also capped at their official value of 40 characters
  • Both NEX and service tokens from NNAS will always be capped to 512 characters. Sending anything longer will be truncated to 512 characters
  • Both NEX and service tokens from NASC will always be capped to 255 characters. Sending anything longer will be truncated to 255 characters

These are the ranges we have to work with here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting-approval Topic has not been approved or denied enhancement An update to an existing part of the codebase
Projects
None yet
Development

No branches or pull requests

1 participant