logo

Saturn - Payment Authorization Wallet

Disclaimer: this is a system in development, subject to change without notice.

Copyright Notice: this document is furnished under an MIT license.

Table of Contents

n/a1.  Introduction
n/a2.  Detailed Operation
n/a2.1.  Sequence Diagram
n/a2.2.  Wallet Initiation
n/a2.3.  Wallet Request UI
n/a2.4.  Payer Authorization
n/a2.5.  Calling the Payment Network
n/a2.6.  Wallet Termination
n/a3.  Message Reference
n/a3.1.  Authorization Request
n/a3.2.  Payment Request
n/a3.3.  Authorization Response
n/a3.4.  Key Encryption
n/a3.5.  "Pass Through" Data
n/a3.6.  Provider Data
n/a3.7.  Signed Authorization
n/a4.  Credential Database
n/a5.  Credential Enrollment
n/a6.  Authorization Processing
n/a6.1.  Decryption
n/a6.2.  Signature Validation
n/a7.  Non-direct Payments
n/a7.1.  Gas Station Payments
n/a8.  Algorithm Support
n/a9.  Security Considerations
n/a10.  Test Vectors
n/a11.  Version

1.  Introduction

This document describes the core components of the Saturn wallet. Note that Saturn is a payment authorization system for end-users, not a payment system. Saturn is heavily influenced by the current "gold standard" for consumer payments, EMVemv.

Compared to EMV, Saturn introduces several enhancements:

Saturn builds on the idea that different payment networks should not need unique user authorizations solutions; only identifiers related to accounts and payment networks need to be adapted. This data is provided in the associated payment credentials (virtual payment cards), potentially making the wallet software universal.

Saturn is also intended to serve as a candidate for the payment authorization part of the EU Identity Wallet [EUIDWeuidw].

2.  Detailed Operation

To guide the reader, this document is based on an example which in turn provides links to the formal definitions.

The Saturn protocol is based on CBOR [RFC8949rfc8949] which is a binary interchange format. However, for documentation purposes, messages are shown in diagnostic notation.

To support cryptographic operations requiring secure transformations of CBOR map objects, Saturn relies on an IETF standard currently in development [CDEcde], which defines deterministic encoding of CBOR.
2.1.  Sequence Diagram
The sequence diagram below outlines the Saturn protocol:
Payer icon provided through the courtesy of wikimedia.orgpayer.
2.2.  Wallet Initiation
The payment process is initiated when the Payer hits a "Pay" button on the Web or scans a QR-code, returning a Wallet activation URL. The Wallet should then use the received URL for performing an HTTP GET (step #1 in the Sequence Diagram) to the Payee service. This operation should return an Authorization Request object (step #2 in the Sequence Diagram) like the following:
{
  1: {
    1: "Space Shop",
    2: "722385402",
    3: "600.00",
    4: "EUR"
  },
  2: ["https://cardnetwork.com", "https://banknet2.org"],
  3: "https://spaceshop.com/receipts/722385402.MNloPyPahXxr43flXzufdQ"
}
Note that the Payee service must set the HTTP Content-Type header parameter to application/cbor.
2.3.  Wallet Request UI
After receival of the Authorization Request, the Wallet should display a UI like the following:
If there are multiple Credential Database entries matching the Payee request, the Payer needs to select (step #3 in the Sequence Diagram) a suitable credential, unless the default (or last used) credential already meets the preferences of the Payer.

If there are no matching payment credentials, the Wallet must provide the Payer with a suitable error message and a cancel button.

If the requested currency differs from the default (as defined by the locale settings of the operating system), it is recommended displaying ISO three-letter abbreviations (USD, EUR, SEK, etc.) rather than short-hand versions like '$' and '€'. See also Payment Request.

2.4.  Payer Authorization
Assuming that the Payer accepts and subsequently authorizes the request (step #4 in the Sequence Diagram) using a biometric operation or PIN, the Wallet should perform an HTTP POST (step #5 in the Sequence Diagram) to the Payee service containing an Authorization Response object like the following:
1010(["https://saturn.standard/v4", {
  0: {
    1: {
      1: "Space Shop",
      2: "722385402",
      3: "600.00",
      4: "EUR"
    },
    2: {
      1: "https://banknet2.org",
      2: "mybank.com"
    }
  },
  1: 3,
  2: {
    1: -29,
    4: {
      1: 2,
      -1: 1,
      -2: h'e812b1a6dcbc708f9ec43cc2921fa0a14e9d5eadcc6dc63471dd4b680c6236b5',
      -3: h'9826dcbd4ce6e388f72edd9be413f2425a10f75b5fd83d95fa0cde53159a51d8'
    },
    7: {
      1: 2,
      -1: 1,
      -2: h'50ae6495cfa2f6435399d539a3f7a3d70a88bc7f4f1afc2d883db1065d9eaf72',
      -3: h'cab412ef81ae3de2136acfd76f7baa3de0c07f8adc391592942f56ff3275088a'
    },
    10: h'44b042d6bcc12894ea05ae4cf23d80ec27535a3d29a07e4f45681693d51e6747c98bac3652d4d28c'
  },
  8: h'384be551cc8fda4803ef9e150207b148',
  9: h'957d107139b2770a23e7b38c',
  10: h'f68500a09170113896bb34cfb64785705729da5b6ad64659efd026f291f74ef0e82f663ad0563807b6da62d86608811febe1bdb2269fe9d06714cf39c2a4c4062e7cb9d643212cdf1c9d9a0b2b2c8b92941a96261b3d2858601086e0e8e64faba6d67ee3e7df534704979977b713a49a918efbb420dbfda022144d299b404295d2efb9ea83658fa35741275ce652f3a1963906f59e17db1f0862b54eb921b99afcf811be22caf2bd61226ed98daae2d81abe66a9b2baa982c9c60a5f8796ace4361a6b51749e2811f7401ec6fc5af7c60ec7ac452a58ff255c5236d16dd15ae619790efafb1b9c20beacfee849e875f9e568b355f58ce89e'
}])
Note that the POST must be directed to the same URL as used by the GET in Wallet Initiation. In addition, the HTTP Content-Type header parameter must be set to application/cbor.
2.5.  Calling the Payment Network
After receiving the Authorization Response, the Payee includes this object in a payment-network-specific request to the designated PaymentNetwork (provided by the selected payment credential). Note that this phase may constitute of multiple request-response pairs.
2.6.  Wallet Termination
After successful (or failed) authorization, the Authorization Response should return a Wallet termination message (step #6 in the Sequence Diagram). This message depends on how the payment process was initiated, and is currently TBD.

3.  Message Reference

This section contains a reference to the components underpinning Saturn messages. The components are based on CBOR map objects.
3.1.  Authorization Request
NameLabelTypeDescription
paymentRequest1mapThe core object, Payment Request.
supportedNetworks2arrayNon-empty list of payment network/method identifiers that the Payee supports. Network identifiers are expressed as CBOR strings (tstr).
See also networkId in the Credential Database.
receiptUrl3tstrOptional: URL to a Payee receipt service.
See also RECEIPTSreceipts.
The Authorization Request represents the primary Payee to Wallet message. In same-device Web contexts this message is also associated with the invocation of the Wallet.
3.2.  Payment Request
NameLabelTypeDescription
commonName1tstrPayee common name to be shown in the Wallet Request UI
Note that common and legal names often differ.
referenceId2tstrPayee reference Id.
Reference Ids must be unique with respect to the Payee.
amount3tstrMonetary amount compatible with the regular expression: ^(0|[1-9][0-9]*)(\.[0-9]+)?$.
Amounts must not use more decimals than is custom for prices for the specific currency.
currency4tstrCurrency expressed in the ISO4217iso4217 alphabetical format.
nonDirect5mapOptional: Also see Non-direct Payments.
3.3.  Authorization Response
An Authorization Response consists of a single CEFcef object, where the outermost element is a COTXcotx wrapper as follows:
1010(["https://saturn.standard/v4", {
CEF container...
}])
Note that the COTX wrapper is included in the encryption process by constituting a part of the Additional Authentication Data (AAD).
The CEF container map keys are as follows:
NameLabelTypeDescription
customData0mapCEF custom (unencrypted) data in the form of a copy of the "Pass Through" Data object fetched from the Signed Authorization object.
algorithm1intCopy of the encContentAlg attribute of the selected payment credential in the Credential Database.
keyEncryption2mapHolds the CEF Key Encryption object.
tag8bstrEncryption algorithm tag.
iv9bstrEncryption algorithm initialization vector (IV).
cipherText10bstrEncrypted data containing a version of the Signed Authorization object where the "Pass Through" Data object has been removed after the completed authorization signature process.
Note that the modified Signed Authorization map object must be updated (before being encrypted), to reflect the removal of the "Pass Through" Data object.
See also Authorization Processing.
3.4.  Key Encryption
NameLabelTypeDescription
algorithm1intCopy of the encKeyAlg attribute of the selected payment credential in the Credential Database.
keyId3"Any"Optional: Copy of the encKeyId attribute of the selected payment credential in the Credential Database.
publicKey4mapOptional: Copy of the encPublicKey object of the selected payment credential in the Credential Database.
Note that keyId and publicKey are mutually exclusive.
ephemeralKey7mapEphemeral ECDH public key.
cipherText10bstrOptional: Encrypted key for key wrapping algorithms.
3.5.  "Pass Through" Data
NameLabelTypeDescription
paymentRequest1mapThrough the inclusion of a copy of the Payment Request in the Payer authorization, this object remains authoritative throughout the payment process (except for interbank operations).
providerData2mapHolds the Provider Data required by the Payee for deriving which payment network to use and how to initiate a compatible payment transaction request.
3.6.  Provider Data
NameLabelTypeDescription
networkId1tstrCopy of the same attribute of the selected payment credential.
serviceLocator2tstrCopy of the same attribute of the selected payment credential.
3.7.  Signed Authorization
NameLabelTypeDescription
passThroughData1mapHolds the "Pass Through" Data object.
payeeHost2tstrHost name or IP address of the invoking Payee, derived from step #1 in the sequence diagram.
accountId3tstrCopy of the same attribute of the selected payment credential.
serialNumber4tstrCopy of the same attribute of the selected payment credential.
platformData5arrayArray holding the name and version of the operating system in [0] and [1] respectively, expressed as CBOR strings (tstr).
walletData6arrayArray holding the name and version of the Wallet software in [0] and [1] respectively, expressed as CBOR strings (tstr).
location7arrayOptional: Array holding the current latitude [0] and longitude [1] of the Wallet device, expressed as CBOR floating point values.
This option depends on Payer privacy settings.
timeStamp8tstrISO date-time string [RFC3339rfc3339] using UTC (T) or local time (Z) format.
authzSignature-1mapAuthorization signature using a CSFcsf object.
For an example, see Signature Validation.

4.  Credential Database

A fundamental part of the Wallet is a local database holding enrolled payment credentials. Note that although credential data types listed here are mainly expressed as CBOR, other representations may be used. The only requirement is that credential data types can be securely mapped back and forth to CBOR.

The data type "ps" denotes a platform-specific solution.

Each entry in the database contains a payment credential according to the following definition:

NameTypeDescription
versiontstrSince credential data may evolve over time, versioning is necessary. This specification covers version: https://saturn.standard/cr/v1.
networkIdtstrPayment network/method identifier. Since payment networks are likely to continue having unique message solutions, the Payee needs to identify the specific network before making a transaction request.
Payment network identifiers may be expressed as URLs or as simple names like "VISA". Note that this concept does not make a distinction between payment methods or "schemes".
Also see Provider Data.
serviceLocatortstrPayment service URL or host name. This attribute enables the Payee to find the end-point of the specific payment service (like a bank), associated with the payment credential.
How to interpret this attribute is dictated by the networkId identifier. If serviceLocator is expressed as a host-name only, a ".well-known" [RFC8615rfc8615] extension would typically be used.
Also see Provider Data.
accountIdtstrAccount identifier associated with the payment credential.
serialNumbertstrSerial number of the payment credential.
cardImagebstrCard image associated with the payment credential. Card images are used for aiding Payer administration of payment credentials as well as being featured in the Wallet Request UI.
Card images must be in SVGsvg format and tentatively having a size of 300×180 pixels.
authzAlgintCOSE signature algorithm to use for creating Signed Authorization objects.
authzKeyHandle"ps"Local handle to the private key to use for creating Signed Authorization objects.
authzPublicKey"ps"Authorization public key for inclusion in Signed Authorization objects.
encContentAlgintCOSE content encryption algorithm to use for creating Authorization Response objects.
encKeyAlgintCOSE key encryption algorithm to use for creating Authorization Response objects.
encPublicKey"ps"Encryption public key to use for creating Authorization Response objects.
Note that encPublicKey objects are provided by credential issuers. In order to serve their primary purpose, preserving privacy, encPublicKey objects must be shared by multiple clients.
encKeyId"Any"Optional: If the encKeyId attribute is defined, it must be featured in Key Encryption objects instead of encPublicKey.

5.  Credential Enrollment

TBD.

6.  Authorization Processing

This section describes how Authorization Response messages should be processed, using the Payer Authorization sample and associated Test Vectors as model data.
6.1.  Decryption
Firstly, the Authorization Response object needs to be decrypted using a private key associated with the supplied CEFcef publicKey or keyId attribute. In the sample, a publicKey attribute was used.

Note that enclosing COTXcotx object must be included in the decryption process.

The decryption process should return two CBOR objects: the "Pass Through" Data object which is already supplied in clear:
{
  1: {
    1: "Space Shop",
    2: "722385402",
    3: "600.00",
    4: "EUR"
  },
  2: {
    1: "https://banknet2.org",
    2: "mybank.com"
  }
}
and another object which after decryption should read like the following:
{
  2: "spaceshop.com",
  3: "FR7630002111110020050014382",
  4: "010049255",
  5: ["Android", "14.1"],
  6: ["Saturn", "1.0.0"],
  7: [38.8882, -77.01988],
  8: "2024-09-01T13:28:02-02:00",
  -1: {
    1: -50,
    4: {
      1: 1,
      -1: 6,
      -2: h'fe49acf5b92b6e923594f2e83368f680ac924be93cf533aecaf802e37757f8c9'
    },
    6: h'2c10f412440ac53649bbcfe2acdf3f9ed2813f9a522392d4175db940562ad69cdd6444ac2de53e1333b0e2cb8ffc26e2f309188733352bbc98db6075d2b8e000'
  }
}
6.2.  Signature Validation
Now combine the objects retrieved during the decryption phase by copying the first object ("Pass Through" Data) to a label 1 of the second object. Note that the length of the resulting map object must be updated to reflect the addition of an item. This operation effectively recreates the Signed Authorization object:
{
  1: {
    1: {
      1: "Space Shop",
      2: "722385402",
      3: "600.00",
      4: "EUR"
    },
    2: {
      1: "https://banknet2.org",
      2: "mybank.com"
    }
  },
  2: "spaceshop.com",
  3: "FR7630002111110020050014382",
  4: "010049255",
  5: ["Android", "14.1"],
  6: ["Saturn", "1.0.0"],
  7: [38.8882, -77.01988],
  8: "2024-09-01T13:28:02-02:00",
  -1: {
    1: -50,
    4: {
      1: 1,
      -1: 6,
      -2: h'fe49acf5b92b6e923594f2e83368f680ac924be93cf533aecaf802e37757f8c9'
    },
    6: h'2c10f412440ac53649bbcfe2acdf3f9ed2813f9a522392d4175db940562ad69cdd6444ac2de53e1333b0e2cb8ffc26e2f309188733352bbc98db6075d2b8e000'
  }
}
Since this object contains a CSFcsf publicKey attribute, it can be validated using "as is".

Note that the authenticity of received public keys must be verified before authorization objects are acted upon!

Unsurprisingly, authorization objects must also be checked for alignment with the specification. Missing, additional, or malformed elements must be rejected.

7.  Non-direct Payments

Non-direct payments represent a group of payment-related scenarios where an initial Payer authorization is followed by one or more operations performed by the Payee, usually without further intervention by the Payer. Here we find gas-station payments, subscriptions, BNPL (Buy Now Pay Later), and deposits.

Non-direct payments typically involve reservation of funds. Subscriptions and BNPL may also be subject to Payer credit considerations.

Although this specification only defines a single non-direct payment scenario, this is intended to serve as a model for additional variants as well.

7.1.  Gas Station Payments
A gas station payment consists of two operations: 1) Reservation of a maximum amount of money to be used. 2) Resolving the reservation by debiting the Payer for the actual cost of the fill-up. Note that a valid receipt (step #7 in the Sequence Diagram) can only be made available after the second phase has been executed.

All non-direct payment profiles must feature a nonDirPayId entry (label 1) holding a unique identifier in the form of a URL. This entry may be followed by other, profile-specific elements required for describing the operation at hand. Below is the gas station payment profile:

NameLabelTypeDescription
nonDirPayId1tstrUnique Id: https://saturn.standard/ndp/gs1
timeOut2intNumber of hours (1-24) the reservation will remain valid before being automatically revoked by the account-holding entity. It is recommended to have a margin of at least 15 minutes.
Since non-direct payments differ from one-off payments, the Wallet UI should also reflect such requests in a meaningful way.

For gas station payments, the following appears like a suitable solution:

8.  Algorithm Support

TBD.

9.  Security Considerations

TBD.

10.  Test Vectors

Equipped with an appropriate diagnostic notation parser like https://cyberphone.github.io/CBOR.js/doc/playground.html and CEFcef/CSFcsf support, the Payer Authorization sample should be possible to decrypt and validate, using the following sample keys.
Authorization key in JWK format:
{
  "kty": "OKP",
  "crv": "Ed25519",
  "x": "_kms9bkrbpI1lPLoM2j2gKySS-k89TOuyvgC43dX-Mk",
  "d": "0flr-6bXs459f9qwAq20Zs3NizTGIEH5_rTDFoumFV4"
}
Authorization key in COSE format:
{
  1: 1,
  -1: 6,
  -2: h'fe49acf5b92b6e923594f2e83368f680ac924be93cf533aecaf802e37757f8c9',
  -4: h'd1f96bfba6d7b38e7d7fdab002adb466cdcd8b34c62041f9feb4c3168ba6155e'
}
Encryption key in JWK format:
{
  "kty": "EC",
  "crv": "P-256",
  "x": "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
  "y": "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg",
  "d": "6XxMFXhcYT5QN9w5TIg2aSKsbcj-pj4BnZkK7ZOt4B8"
}
Encryption key in COSE format:
{
  1: 2,
  -1: 1,
  -2: h'e812b1a6dcbc708f9ec43cc2921fa0a14e9d5eadcc6dc63471dd4b680c6236b5',
  -3: h'9826dcbd4ce6e388f72edd9be413f2425a10f75b5fd83d95fa0cde53159a51d8',
  -4: h'e97c4c15785c613e5037dc394c88366922ac6dc8fea63e019d990aed93ade01f'
}

11.  Version

API version: 0.51
Document version: 2024-09-30
Author: Anders Rundgren (anders.rundgren.net@gmail.com)