Content:
From February 2023, eBay will require certain API calls made on behalf of UK and EU domiciled sellers to include a digital signature. The eBay developer site explains that this change is “due to regulatory requirements applicable to [our] EU/UK sellers”.
If your eBay application uses an API call subject to this change, you’ll need to alter your application to generate the required digital signature.
While eBay do provide documentation, at the time of writing, this is somewhat lacking. This article will go through the steps required to create the required digital signature, and hopefully demystify digital signatures.
This guide is not language specific, and the code blocks are designed to provide a basic representation, rather than a concrete solution. Be sure to check out the links at the bottom of the article for more language-specific walkthroughs, which include working code to get you started.
If you’re new to the eBay API, be sure to check out our range of guides to get you started.
What Is a Digital Signature?
A good starting point would be to look at what a digital signature is, and why it’s now needed for certain requests.
Digital signatures are a method of ensuring the authenticity of a HTTP request. By creating a signature of the headers and body content (if present), the recipient is able to verify that the request has not been tampered with during transmission.
As the developer has a unique private key only known to them, and eBay has the corresponding public key, it’s not possible for an attacker to create a new signature for their tampered content. The only way to do this would be by using the correct private key owned by the developer.
When dealing with financial transactions, particularly with APIs that allow the creation of orders or refunds, it’s easy to see why digital signatures are beneficial, and will be required by regulations in the UK/EU.
Getting a Signing Key
A signing key can be obtained using the createSigningKey
endpoint of the eBay Key Management API. The eBay documentation for this endpoint can be found here.
There are two possible key types that can be used to create a signing key – ED25519 and RSA. ED25519 is recommended, due to the shorter key lengths (and therefore shorter request header size).
As with any API call, an access token needs to be generated. Use the scope https://api.ebay.com/oauth/api_scope
to generate the access token.
The request to the Key Management API requires two headers, one of which uses an API access token.
'Authorization': 'Bearer access_token'
'Content-Type': 'application/json'
A payload describing the signing algorithm chosen needs to be send in the request body.
'{"signingKeyCipher": "ED25519"}'
The response is a JSON string, which can be parsed using a JSON parser.
The main parts of the response you’ll want to make a note of are as follows:
privateKey
: The private key needed to create your digital signature. This is the only time you’ll be able to get this value – if you lose it, you’ll need to generate a new keyjwe
: The JWE public key element corresponding to your private key.
The publicKey
and signingKeyId
are not needed to create the signature, but might prove handy to keep copies of. signingKeyId
in particular is useful, as it allows you to retrieve key info from the API later on (excluding the privateKey
field).
Creating the Signature-Input Header
The Signature-Input header contains a list of the elements which make up the request header.
For a GET request, your header will contain the following.
"x-ebay-signature-key" "@method" "@path" "@authority"
For a POST request, you’ll also have a content digest, which needs to be included as well.
"content-digest" "x-ebay-signature-key" "@method" "@path" "@authority"
This string should be surrounded by brackets, and given a name. The name is used where multiple signatures are present. This is not the case here, so stick to sig1
.
sig1=("x-ebay-signature-key" "@method" "@path" "@authority")
The final addition to the signature input header is a creation timestamp. This should be a unix timestamp, rounded to the nearest whole second.
;created=1670882848
Add this to the end of the signature input string created above.
'sig1=("x-ebay-signature-key" "@method" "@path" "@authority");created={creation_date}'
It’s vital to use an up-to-date creation timestamp on each request, as the API will reject signatures it considers to be too far from the current timestamp. From testing, the API only has a small window of around a minute or two where a timestamp will be accepted.
An important note is that the signature input used here is also used when creating the digital signature, which is explained in more detail below. The signature, however, requires the variable name (e.g. sig1=
) to be omitted.
We would therefore suggest creating the full string (including timestamp), and appending the signature name when creating the header. You can then use this string to create both the signature input header, and the signature itself.
Creating a Content Digest
If you’re using one of the few POST API calls requiring a digital signature, you will also need to include a content digest.
The content digest is used to verify that the contents of the request body have not been tampered with, by calculating the content digest and comparing it to the content digest in the request header.
The eBay API requires that the digest is calculated using SHA-256. The result should be a base64 string.
The following is the example of a content digest, provided by eBay (which itself used the example from the ITEF document).
'{"hello": "world"}' # X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
This data should be hashed as a plain text string, despite appearing to have a JSON-like structure.
When sending the calculated value in the request header, it should be formatted as sha-256=:digest:
.
sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
Creating the Signature
This is the most important part of the request, and it’s the one that’s easiest to get wrong. The formatting of the data being signed must be exactly correct, as outlined below, to generate the correct signature.
There are a few steps required to create the signature successfully, which are broken down below.
Signature Parameters
Your signature input string defines the parameters which need to be included in your signature. Don’t forget, though, that the signature input parameters themselves also need to be present.
For example, with a signature input containing
"content-digest" "x-ebay-signature-key" "@method" "@path" "@authority"
your signature needs to be made up of the following:
x-ebay-signature-key
: Public Key JWE returned by eBay Key Management API@method
: HTTP request method e.g. GET@path
: URL path (section of the URL after the hostname, excluding parameters)@authority
: Hostname@signature-params
: Signature input parameters, minus the signature input name (optional)
If you’re not using a content digest, be sure to leave this out.
Each entry needs to be separated using a line break (\n) character.
The basic format required (including a content digest) is demonstrated below.
'"x-ebay-signature-key": {ebay_public_key_jwe}\n'
'"@method": {method}\n'
'"@path": {path}\n'
'"@authority": {authority}\n'
'"@signature-params": '{signature_params}'
'"content-digest": 'sha-256=:{digest}:'
And here is an example including values for each entry.
'"x-ebay-signature-key": eyJ6aXAiOiJERU...\n'
'"@method": GET\n'
'"@path": /sell/finances/v1/transaction\n'
'"@authority": apiz.ebay.com\n'
'"@signature-params": ("x-ebay-signature-key" "@method" "@path" "@authority");created=1670882848\n'
'"content-digest": 'sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:'
The parameters are now ready to be signed.
Loading Your Private Key
The corresponding private key from the eBay Key Management API is used to create the signature.
The API only returns the private key itself.
X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
Some key management libraries expect a fully-formed private key, including a header and footer as shown below.
-----BEGIN PRIVATE KEY-----\n
X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n
-----END PRIVATE KEY-----
Line break characters have been added here, to highlight the fact that the header and footer are on their own lines.
If your library requires this, consider either storing the private key in a separate file in the required format, or add the header and footer manually in your code.
'-----BEGIN PRIVATE KEY-----\n{ebay_private_key}\n-----END PRIVATE KEY-----'
Creating the Signature
The private key should be used to create a signer object using the required algorithm.
You’ll need to check how to do this for the programming language you’re using, and you may need to install additional libraries to achieve this.
Once you’ve loaded your key into a signer, you can create a signature by signing the signature parameters with your signer.
The signature result needs to be base64 encoded, and may need converting (depending on the output type used by your signer).
Sending the Signed API Request
Sending the request brings together all of the elements that have been created, to form the request header.
headers = {
"Signature-Input": 'sig1={signature_params}',
"Signature": 'sig1=:{signature}:',
"x-ebay-signature-key": {ebay_public_key_jwe},
"x-ebay-enforce-signature": 'true',
"content-digest": 'sha-256=:{digest}:'
}
Ensure the "Signature"
and "Signature-Input"
values are prefixed with sig1=
, with the signature also being surrounded by colons (:
). The "content-digest"
value, if present, should be prefixed with sha-256=
, and again, surrounded by colons.
An example with dummy values can be found below.
headers = {
"Signature-Input": sig1=("x-ebay-signature-key" "@method" "@path" "@authority");created=1670882848,
"Signature": sig1=:u1jEapg9bm0...:,
"x-ebay-signature-key": eyJ6aXAiOiJERU...,
"x-ebay-enforce-signature": 'true',
"content-digest": sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
}
If you’re sending a POST request, be sure to include the content in the request body.
If everything has been done correctly, you should get a valid response from the API.
Conclusion
Once you understand the process, it’s actually fairly straightforward. It’s unfortunate that eBay have chosen to rely on a complex third-party draft specification to explain the signature creation, rather than creating their own simplified walkthrough to highlight the key points.
Hopefully, this guide goes some way to clearing up issues you may be having in understanding the process for creating a digital signature.
Be sure to check out our other digital signature-related articles, which look at more specific solutions using a variety of programming languages. These guides are linked below: