Whitepaper Appendix B: Verifiable PayString Protocol Integration
As an alternative to the LNURL standard (Bech32 encoded URL) used in the OpenVASP Travel Rule Protocol, the PayString protocol from Ripple Labs allows for a secure and private out-of-band mechanism to retrieve payment addresses corresponding to a PayString.
Integrating the PayString protocol into the TRISA flow can enhance the protocol in several aspects:
1. Determining by Sender (originator) if Receiver (beneficiary) is a VASP: The Risk of Sending Private Information to the Wrong Entity
In the TRISA flow, the sending user provides the payment address to the Sender VASP. It is not possible for the Sender VASP to know from the payment address the Receiver VASP without blockchain analytics. TRISA suggests two solutions:
• Asking the sending user if they are sending to a VASP.
• VASP address confirmation protocol.
Both the above approaches currently have constraints as described in the respective sections. Some of the potential ways that PayString can solve these constraints are: Adding “PayString domain” in the EV KYV identity certificate. This:
a. Allows the Receiver VASP to send the signed payment address to the Sender VASP. This proves that the identity who signed this address (i.e. the Receiver VASP) provided this payment address.
b. Allows the Receiver VASP to send “proof of control signature” to the Sending VASP to prove the ownership of the private key corresponding to the payment address.
The above two proofs together tie the ownership of a private key for an on- ledger payment address to the identity of the Receiver VASP.
2. Determining by Receiver if Sender is a VASP:
This is a challenging problem when sending to a ledger address since the address is not actively provided by the Receiver VASP but rather is sent by the Sender to the Sending Institution. From the perspective of the Receiver VASP, determining if the Sending Institution is a VASP and any corresponding compliance implications is cumbersome at best.
When a payment is instead sent to a PayString, the on-ledger payment address to make the transaction is sent by the Receiver VASP and signed with their private key (that identifies the VASP) after determining if the sending side is a VASP or not.
A corollary benefit of PayString is that it precludes both false positives and false negatives, regardless of what combination of VASPs and non-VASPs are involved in a transaction. That is, a payment to a PayString will definitively determine the counter-party without ambiguity. This is impossible in a payment to an on-ledger address unless every VASP participates in the same compliance system.
3. PayString enhances the compliance screening and privacy of TRISA because the blockchain address to make the payment is only sent by the Receiver VASP to the Sending VASP after:
a. Receiver VASP and the Sending VASP have verified each other’s identity and have decided to proceed with the transaction.
b. Each side has received the required Travel Rule information about the Sender and the Receiver.
Integration of PayString with TRISA for VASPs Flow
The participating entities i.e. the Sending and Receiving institutions MUST acquire the following three certificates:
- EV KYV Identity Certificates
- Transactions Signing Certificates for VASPs
- Web PKI domain certificate (Non-VASP certs)
The integrated protocol flow begins at the Sending VASP as a PayString client. The prerequisite is Sender issues a Payment Request that contains the Receiver’s PayString and the transaction amount along with the other meta-data to the Sending VASP. The Sending VASP resolves the PayString URI to VASP’s URL as described in the PayString discovery protocol.
- The Sending VASP establishes a secure, mutually authenticated TLS 1.3 connection (non-VASP web PKI certificate) with the receiving endpoint.
- If the TLS session is successfully established, Sending VASP (PayString client) generates the signed PaymentSetupDetails message. Among other optional fields, the body of the message MUST contain:
- isVASP field set to true to indicate to the receiving endpoint that the sending endpoint is a VASP.
- transactionAmount field set to the amount of intended payment
PaymentSetupDetails
Field name | Required/ Optional | Type | Description |
identity | optional | Identity | TBD |
isVASP | required | boolean | Indicates if the Endpoint is a VASP. Defaults to false |
transactionAmount | optional | integer | Amount of intended payment |
currency | optional | string | ISO currency code |
scale | optional | integer | Orders of magnitude necessary to express one regular unit of the currency e.g. a scale of 3 requires an amount of 100 to equal 1 US dollar |
memo | optional | string | Specifies additional metadata |
Identity
Field name | Required/ Optional | Type | Description |
fullLegalName | required | string | Full legal name of the Sending Endpoint |
postalAddress | required | string | Principal place of Business Address of the Sending Endpoint |
Then Sending VASP sends an HTTP POST request with path parameter /payment- setup-details to the receiving endpoint (PayString server) with the appropriate request headers as described in the HTTP request and response headers.
3. Upon receiving this PaymentSetupDetails message, the receiving endpoint (PayString server) parses the message body for isVASP field to check if the sending endpoint is a VASP. The receiving endpoint (PayString server/beneficiary VASP) generates a signed Response message that includes:
-
- “Travel Rule” as a compliance requirement in the list of complianceRequirements field.
- isVASP field set to true to indicate to the Sending VASP that the Receiving endpoint is a VASP.
- redirectURI field set to redirect URI to redirect PayString client (Sending VASP) to TRISA server to initiate the TRISA flow.
- An empty paymentInformation field. The Beneficiary VASP MUST NOT send the payment address information yet.
Response
This message is sent by the Receiving Endpoint in response to the PaymentSetupDetails message sent by the Sending Endpoint.
Field name | Required/Optional | Type | Description |
id | required | string | The value of this field is the UUID
as described in RFC 4122 |
identity | required | Identity | TBD |
isVASP | required | boolean | Indicates if the Endpoint is a
VASP. Defaults to false |
redirectURI | optional | string | A redirect URI for PayString client |
transactionAmount | optional | integer | Amount of intended payment |
currency | optional | string | ISO currency code |
scale | optional | integer | Orders of magnitude necessary to express one regular unit of the currency
e.g. a scale of 3 requires an amount of 100 to equal 1 US dollar |
expirationTime | required | integer (milliseconds from epoch) | This message is considered void and payments MUST NOT be made on the specified address in the paymentInformation field
past the specified timestamp |
paymentInformation | required | PaymentInformation | Contains details as to how a payment can be made to the Beneficiary. Defaults to empty |
complianceRequirements | required | string[] | List of the regulatory requirements that the Beneficiary must satisfy during the proposed transaction. Allows the client to send relevant compliance data corresponding to the data in this field. e.g Travel Rule data in case of Travel rule compliance requirement. Defaults to empty list |
previousMessage | required | string | This is the previous
PaymentSetupDetails message received from the Sending Endpoint. |
memo | optional | string | Specifies additional metadata to a payment |
PaymentInformation
Field name | Required/Optional | Type | Description |
addresses | required | Address[] | The value of this field is an array of one or more JSON objects of type addresses |
proofOfControlSignature | optional | ProofOfControlSignature | The value of this field is a JSON object as described in ProofOfControlSignature. This is the digital signature proving ownership of the on-ledger address |
identity | optional | string | This field may specify any additional identity information about the PayString owner or PayString server |
payid | optional | string | The value of this field is the PayString URI in the client request that identifies the payment address information |
memo | optional | string | Specifies additional metadata corresponding to a payment |
addresses
This is a required field in the PaymentInformation message.
Field name | Required/Optional | Type | Description |
paymentNetwork | required | string | The value of this field is the payment-network as specified in the client request’s “Accept” header
(e.g. XRPL) |
environment | optional | string | The value of environment as specified in the client request’s “Accept” header (e.g. TESTNET) |
addressDetailsType | required | string | The value of this field is the
string “CryptoAddressDetails” or “ACHAddressDetails” |
addressDetails | required | CryptoAddressDetails||A CHAddressDetails | The value of this field is the address information necessary to send payment on a specific network as described in addressDetails |
addressDetails
This is a field in the PaymentInformation message. addressDetails for each specific ledger MUST be registered at paystring.org.
Address Type | Field name | Required/ Optional | Type | Description |
CryptoAddressDetails | address | required | string | On-ledger address |
tag | optional | string | Tagging mechanism used by some cryptocurrencies to distinguish accounts contained within a singular address. E.g XRP | |
ACHAddressDetails | accountNumber | required | string | ACH account number |
routingNumber | required | string | ACH routing number |
ProofOfControlSignature
This is an optional field in the PaymentInformation message.
Field name | Required/ Optional | Type | Description |
publicKey | required | string | on-ledger public key of the PayString server |
payID | required | string | PayString of the receiver. |
hashAlgorithm | required | string | The value of this field is the hash algorithm used to hash the entire contents of the “ProofOfControlSignature” message. e.g. “SHA512” |
signature | required | string | The value of this field is the digital signature over the hash of the entire contents of the “ProofOfControlSignature” message using the private key corresponding to the public key in “publicKey”. This is a proof that the owner of the private key corresponding to the public key in the “publicKey” used to sign this message is the owner of the on-ledger public key in “publicKey” |
4. Upon receiving this Response message, the Sending endpoint (PayString client) parses the message body for isVASP field to check if the Receiving endpoint is a VASP. If it is, the PayString client (Sending VASP) forwards the request to the TRISA client. TRISA client parses the redirectURI field to initiate a secure, mutually authenticated TLS connection between VASPs by the Sending VASP to assure privacy of data in transit using EV KYV identity certificate.
5. Upon receiving the Sending VASP’s EV KYV identity certificate, the Receiving VASP verifies the certificate and decides if they want to proceed with the transaction with the Originating VASP. If they do, they send their EV KYV identity certificate to the Sending VASP.
6. Upon receiving the Receiver VASP’s TRISA identity certificate, the Sending VASP verifies the certificate and decides if they want to proceed with the transaction. If they do, the Sending VASP sends a “transaction identification message”. The transaction identification message MUST contain the amount and Travel Rule information as described in the TRISA paper.
Note here that there are two changes in the TRISA transaction identification message here:
a. Sending VASP sends an additional field that “PayString” that includes:
-
- receiver’s PayString,
- payment-network, e.g. BTC, XRPL, ACH, etc.
- environment, e.g. testnet, devnet, mainnet, etc.
b. Sending VASP does not send the “Blockchain” field as described in the TRISA flow. This is because this transaction identification message is a query for the Receiving VASP for payment address corresponding to the queried “PayString” field.
- 1. Upon receiving the “transaction identification message”, Receiving VASP perform the following steps:
-
- Performs basic PayString protocol with the PayString server to retrieve PaymentInformation corresponding to the queried “PayString”
- Sends a signed receipt to the Sending VASP. The receipt MUST contain the Beneficiary’s information and signed PaymentInformation.
- 2. Sending VASP extracts the payment address from PaymentInformation and posts the transaction and receives a transaction ID.
- 3. Sending VASP posts the signed transaction ID to the Receiving VASP.
For more details on message formats for PayString flow including additional messages such as InvoiceRequest, InvoiceResponse, ComplianceData, etc. refer to the PayString Protocol whitepaper: https://paystring.org/whitepaper.pdf