Copyright Notice: this document is furnished under an MIT license.
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 Digital Identity (EUDI) Wallet [EUDIW].The Saturn protocol is based on CBOR [RFC8949] which is a binary interchange format. However, for documentation purposes, messages are shown in diagnostic notation.
To support cryptographic operations requiring secure transformations of CBORmap
objects,
Saturn relies on an IETF standard currently in development [CDE],
which defines deterministic encoding of CBOR.
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:
Payee
service must set the
HTTP Content-Type
header parameter
to application/cbor
.
Wallet
should display a UI like the following:
If there are multiple Credential Database entries
matching the Authorization 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
.
In the non-normative sample UI, credential selection is performed through swiping the card images.
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.
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:
Content-Type
header parameter must be set to application/cbor
.
Payee
must perform a number of checks
on the Unencrypted Data object including:
Payee
.Payer
with
a suitable error message,
Payee
includes this object in a payment-network-specific request to the designated
Payment
Network
(provided by the selected payment credential).
Note that this phase may constitute of multiple request-response pairs.
Payee
must 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.
map
objects.
In the tables outlining the map
objects,
"Name"
refers to symblic name used for documentation purposes only,
"Label"
refers to the actual CBOR integer value used as key, while
"Type"
refers to the type of the value component of an entry.
"https://cyberphone.github.io/saturn/..."
identifiers
represent temporary name allocations.
map
object, embedded by a COTX wrapper:1010(["https://cyberphone.github.io/saturn/areq/v1", {
}])
Name | Label | Type | Description |
---|---|---|---|
paymentRequest | 1 | map | Payment Request is the core Payee request object. |
supportedNetworks | 2 | array | Non-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. |
receiptUrl | 3 | tstr | Optional: URL to a Payee receipt service.See also RECEIPTS. |
Payee
to Wallet
message. In same-device Web contexts this message is also associated with the invocation of the Wallet
.
Name | Label | Type | Description |
---|---|---|---|
commonName | 1 | tstr | Payee common name to be shown in the Wallet Request UINote that common and legal names often differ. |
amount | 2 | tstr | Monetary 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. |
currency | 3 | tstr | Currency expressed in the ISO4217 alphabetical format. |
referenceId | 4 | tstr | Payee reference Id. Reference Ids must be unique with respect to the Payee . |
nonDirectPayment | 5 | cotx | Optional: See also Non-direct Payments (NDP). |
1010(["https://cyberphone.github.io/saturn/ares/v1", {
}])
map
keys are as follows:Name | Label | Type | Description |
---|---|---|---|
customData | 0 | map | CEF custom (unencrypted) data in the form of a copy of the Signed Authorization object where all map objects except for the Unencrypted Data object have been removed.Also see Decryption. |
algorithm | 1 | int | Copy of the encContentAlg attribute of the selected payment credential in the Credential Database. |
keyEncryption | 2 | map | Holds the CEF Key Encryption object. |
tag | 8 | bstr | Encryption algorithm tag. |
iv | 9 | bstr | Encryption algorithm initialization vector (IV). |
cipherText | 10 | bstr | Encrypted version of the outermost map object of the Signed Authorization object where the Unencrypted Data object has been removed.Also see Decryption. |
Name | Label | Type | Description |
---|---|---|---|
algorithm | 1 | int | Copy of the encKeyAlg attribute of the selected payment credential in the Credential Database. |
keyId | 3 | " Any" | Optional: Copy of the encKeyId attribute of the selected payment credential in the Credential Database. |
publicKey | 4 | map | Optional: Copy of the encPublicKey object of the selected payment credential in the Credential Database. Note that keyId and publicKey are mutually exclusive. |
ephemeralKey | 7 | map | Ephemeral ECDH public key. |
cipherText | 10 | bstr | Optional: Encrypted key for key wrapping algorithms. |
Name | Label | Type | Description |
---|---|---|---|
paymentRequest | 1 | map | Through 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). |
providerInfo | 2 | map | Holds the Provider Info required by the Payee for deriving which payment network to use and how to initiate a compatible payment transaction request. |
payeeHost | 3 | tstr | Host name or IP address of the invoking Payee , derived from the URL obtained in step #1 in the sequence diagram.The purpose of the payeeHost attribute is to provide a means for a Payment Network to verify that the origin of a received Authorization Response matches that of the Payee . This is essentially an inverted version of the phishing protection method used by WebAuthn [WEBAUTHN].The security of this arrangement also depends on that forwarded Payee requests are properly authenticated. |
timeStamp | 4 | tstr | ISO date-time string [RFC3339] using UTC (T) or local time (Z) format. The purpose of the timeStamp attribute is to provide a means for an Issuer to verify the "freshness" of a received Authorization Response. The recommended method is using a cache holding a hash of the associated Signed Authorization and its timeStamp, where the latter is used to automatically remove a cache entry when the authorization is considered to be expired. This arrangement is either used for protection against replay, or for supporting idempotent operation.Note that authorizations that already have expired or are too new must be rejected. Tentative lower limit: timeStamp > currentTime - 600s Tentative higher limit: timeStamp < currentTime + 60s |
Name | Label | Type | Description |
---|---|---|---|
networkId | 1 | tstr | Copy of the same attribute of the selected payment credential in the Credential Database. |
serviceLocator | 2 | tstr | Copy of the same attribute of the selected payment credential in the Credential Database. |
Issuer
to return messages to the Payer
like "Out of funds" through the regular transaction channel, and that without revealing any personal information to intermediaries. In addition, Response Encryption also serves as a strong nonce, ensuring that Signed Authorization objects become unique, irrespective of Authorization Request data and time-stamps.Payer
to provide additional information which could be needed for high-value or "suspicious" transaction requests.Name | Label | Type | Description |
---|---|---|---|
algorithm | 1 | int | Copy of the encKeyAlg attribute of the selected payment credential in the Credential Database. |
instanceKey | 2 | bstr | Random encryption key, initialized for each authorization request. The length of the instanceKey attribute must match the algorithm. |
1010(["https://cyberphone.github.io/saturn/sig/v1", {
}])
map
keys are as follows:Name | Label | Type | Description |
---|---|---|---|
unencryptedData | 1 | map | Holds the Unencrypted Data object. |
responseEncryption | 2 | map | Holds the Response Encryption object. |
accountId | 3 | tstr | Copy of the same attribute of the selected payment credential in the Credential Database. |
serialNumber | 4 | tstr | Copy of the same attribute of the selected payment credential in the Credential Database. |
platformData | 5 | array | Array holding the name and version of the operating system in [0] and [1] respectively, expressed as CBOR strings (tstr). |
walletData | 6 | array | Array holding the name and version of the Wallet software in [0] and [1] respectively, expressed as CBOR strings (tstr). |
location | 7 | array | Optional: 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. |
authzSignature | -1 | map | Authorization signature using a CSF object. |
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:
Name | Type | Description |
---|---|---|
version | tstr | Since credential data may evolve over time, versioning is necessary. This specification covers version: https://cyberphone.github.io/saturn/cred/v1 . |
networkId | tstr | Payment 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". See also Provider Info. |
serviceLocator | tstr | Payment 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/" [RFC8615] URL extension would typically be used.See also Provider Info. |
accountId | tstr | Account identifier associated with the payment credential. See also Signed Authorization. |
serialNumber | tstr | Serial number of the payment credential. See also Signed Authorization. |
cardImage | bstr | Card 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 SVG format and tentatively having a size of 300×180 pixels. |
authzAlg | int | COSE 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. |
encContentAlg | int | COSE content encryption algorithm to use for creating Authorization Response objects. |
encKeyAlg | int | COSE 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. |
Note that enclosing COTX object must be included in the decryption process.
The decryption process should return two CBOR objects.
1. The Signed Authorization object where allmap
objects
except for the Unencrypted Data object have been removed.
Note that this item is already supplied in clear:
map
with the first map
(Unencrypted Data).
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:
Note that the authenticity of received public keys must be verified before authorization objects are acted upon!
Authorization objects must also be checked for alignment with the specification. Missing, additional, or malformed elements must be rejected.
See also timeStamp in Unencrypted Data.
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.
1010([
ndpObjectId,
])
tstr
).
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. For gas station payments, ndpObjectId must be set to: "https://cyberphone.github.io/saturn/ndp/gas"
, while the Additional Parameters consist of single CBOR integer (int
) holding the number 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.
1010(["https://cyberphone.github.io/saturn/ndp/gas", 2])
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:
Name | Description |
---|---|
Ed25519 |
Authorization (signature) algorithm. |
ESP256 | |
ECDH-ES+A128KW |
Key encryption algorithm for usage with P-256 and X25519 keys. |
ECDH-ES+A256KW | |
A128GCM |
Content encryption algorithm. |
A256GCM |
anders.rundgren.net@gmail.com
)