discord-bot/Clients/PsnClient
2019-11-06 03:45:31 +05:00
..
certificates attempt at proper tls validation for sony game update servers 2019-03-05 05:12:37 +05:00
POCOs implement check for ps3 firmware update 2019-08-28 21:29:39 +05:00
Utils organize clients in filesystem similar to solution structure 2019-01-30 16:20:26 +05:00
CustomTlsCertificatesHandler.cs attempt at proper tls validation for sony game update servers 2019-03-05 05:12:37 +05:00
PsnClient.cs update to c# 8.0 syntax, mostly for .Substring() 2019-11-06 03:45:31 +05:00
PsnClient.csproj upgrade library projects to .net standard 2.1 2019-11-01 00:05:54 +05:00
readme.md some docs 2019-04-01 22:52:27 +05:00

PSN Client

For obvious reasons, there's no official documentation on any Sony APIs. Everything was reverse-engineered using web store UI or from various wikis/forums.

PSN Store API

You can access web store at https://store.playstation.com/, which is working on top of their store API, which is convenient.

General workflow is as follows:

  1. Get session (even for anonymous access)
  2. Get storefront information
  3. Call various controllers to search or to get additional item information by its ID

Some terminology:

  • product code is the game ID, of the form NPEB12345.
  • content id is the unique PSN content ID that can be used to resolve its metadata. There's no straight way to map product code to any associated content id.
  • container id is the PSN content aggregation ID that is used to organize the content (i.e. store navigation category like a menu entry, or sale event). Container can include other containers in it.
  • entitlement is the content license granted to the account. You get this by purchasing the content, downloading free content, or by redeeming a PSN code.

At the startup we run a task that enumerates all available PSN storefronts, and then recursively scrapes every container on respective front page to collect all available content ids for any PS3 content that is still available.

Many de-listed or replaced titles are no longer available through anonymous API calls (they require authenticated session with respective entitlements given to the account).

There are rare cases where resolving metadata by content id still works, but there are no links for it anywhere on the store. You can still find such content using the search API.

Game Update API

This is a separate API that can give title update information by product code.

One quirk of this endpoint is that Sony uses non-public root CAs for TLS certificates, only redistributing their public keys in the PS3 firmware updates.

In dotnet core there's no easy way to implement custom certificate pinning / chain validation.

There are two possible ways:

  1. Importing root CA certificates to the Trusted Root CAs certificate store, so the default validation can work as expected.

    This, however, only works on Windows, and will show a confirmation prompt for every certificate being imported.

    On Linux it's much worse and require black magic to work, and is inconsistent between different distros (google SSL_CERT_DIR and SSL_CERT_FILE). The main problem is that this overrides the system/user certificate store to contain only the certificates specified, so any request to any other resource will fail.

  2. Manual certificate chain validation. As one might expect, this is not trivial or easy to implement.

    What we do right now, is to check certificate Issuer on every request, and if it matches the custom Sony CA, we do manual chain validation, and then cache the result for this specific server certificate. We explicitly ignore any revocation checks (as CAs are not public) and also ignore any errors due to untrusted root (as, again, CAs are not public).

    Otherwise we simply forward the validation call to the default handler that is using proper system/user certificate store.

Title Metadata API

TMDB API is used by the PS3 dashboard / shell / UI to show some game information using product code. We mainly use this to get the game thumbnail for embeds, falling back to PSN metadata when it's not available.

The main quirk here is how the URL is constructed using a specific HMAC key and ID format.