Sample code for 30+ languages & platforms
Dart Requires Chilkat v11.0.0+

ebay: Add Digital Signature to HTTP Request

See more eBay Examples

Demonstrates how to add a digital signature to an ebay HTTP request.

Chilkat Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // This example requires the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // Note: Ebay provides a Key Management API
  // See https://developer.ebay.com/api-docs/developer/key-management/overview.html

  // The following test keys can be used: 
  // 
  // Ed25519 
  // 
  // Private Key:
  // 
  // -----BEGIN PRIVATE KEY-----
  // MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF
  // -----END PRIVATE KEY-----

  final strPrivateKey = 'MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF';

  // Public Key:
  // 
  // -----BEGIN PUBLIC KEY-----
  // MCowBQYDK2VwAyEAJrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=
  // -----END PUBLIC KEY-----

  final strPublicKey = 'MCowBQYDK2VwAyEAJrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=';

  // This example assumes you got a JWE for your given private key from the Ebay Key Management REST API.
  // This JWE is just for example:
  final strJwe = 'eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwidGFnIjoiSXh2dVRMb0FLS0hlS0Zoa3BxQ05CUSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiaFd3YjNoczk2QzEyOTNucCJ9.2o02pR9SoTF4g_5qRXZm6tF4H52TarilIAKxoVUqjd8.3qaF0KJN-rFHHm_P.AMUAe9PPduew09mANIZ-O_68CCuv6EIx096rm9WyLZnYz5N1WFDQ3jP0RBkbaOtQZHImMSPXIHVaB96RWshLuJsUgCKmTAwkPVCZv3zhLxZVxMXtPUuJ-ppVmPIv0NzznWCOU5Kvb9Xux7ZtnlvLXgwOFEix-BaWNomUAazbsrUCbrp514GIea3butbyxXLNi6R9TJUNh8V2uan-optT1MMyS7eMQnVGL5rYBULk.9K5ucUqAu0DqkkhgubsHHw';

  final sbBody = CkStringBuilder();
  sbBody.append('{"hello": "world"}');

  print('Body of request:');
  print(sbBody.getAsString());

  // -------------------------------------------------
  // Build the signature base string...

  final sbSigBase = CkStringBuilder();

  sbSigBase.append('"content-digest": sha-256=:');
  sbSigBase.append(sbBody.getHash('sha256', 'base64', 'utf-8'));
  sbSigBase.append(':\n');

  sbSigBase.append('"x-ebay-signature-key": ');
  sbSigBase.append(strJwe);
  sbSigBase.append('\n');

  sbSigBase.append('"@method": POST\n');

  // This is the path part of the URL without query params...
  sbSigBase.append('"@path": ');
  sbSigBase.append('/verifysignature');
  sbSigBase.append('\n');

  // The is the domain, such as "api.ebay.com" w/ port if the port is something unusual.
  // In this example, we're testing against a local docker test server (see the info at https://developer.ebay.com/develop/guides/digital-signatures-for-apis)
  // Normally, I think it would just be "api.ebay.com" instead of "localhost:8080".
  sbSigBase.append('"@authority": ');
  sbSigBase.append('localhost:8080');
  sbSigBase.append('\n');

  sbSigBase.append('"@signature-params": ');

  final sbSigInput = CkStringBuilder();
  sbSigInput.append('("content-digest" "x-ebay-signature-key" "@method" "@path" "@authority")');
  sbSigInput.append(';created=');

  final dt = CkDateTime();
  dt.setFromCurrentSystemTime();
  final unixTimeNow = dt.getAsUnixTimeStr(false);
  sbSigInput.append(unixTimeNow);

  sbSigBase.appendSb(sbSigInput);

  // -------------------------------------------------
  // Sign the signature base string using the Ed25519 private key

  final bdPrivKey = CkBinData();
  bdPrivKey.appendEncoded(strPrivateKey, 'base64');

  final privKey = CkPrivateKey();
  try {
    privKey.loadAnyFormat(bdPrivKey, '');
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final bdToBeSigned = CkBinData();
  bdToBeSigned.appendSb(sbSigBase, 'utf-8');

  final eddsa = CkEdDSA();
  final String sigBase64;
  try {
    sigBase64 = eddsa.signBdENC(bdToBeSigned, 'base64', privKey);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  print('sigBase64:');
  print(sigBase64);

  // ----------------------------------------------------------
  // Send the JSON POST

  final http = CkHttp();

  http.setRequestHeader('x-ebay-signature-key', strJwe);

  final sbContentDigestHdr = CkStringBuilder();
  sbContentDigestHdr.append('sha-256=:');
  sbContentDigestHdr.append(sbBody.getHash('sha256', 'base64', 'utf-8'));
  sbContentDigestHdr.append(':');
  http.setRequestHeader('Content-Digest', sbContentDigestHdr.getAsString());

  final sbSigHdr = CkStringBuilder();
  sbSigHdr.append('sig1=:');
  sbSigHdr.append(sigBase64);
  sbSigHdr.append(':');
  http.setRequestHeader('Signature', sbSigHdr.getAsString());

  sbSigInput.prepend('sig1=');
  http.setRequestHeader('Signature-Input', sbSigInput.getAsString());

  // Add this header to make eBay actually check the signature.
  http.setRequestHeader('x-ebay-enforce-signature', 'true');

  // Set the OAuth2 access token to add the "Authorization: Bearer <access_token>" to the header.
  http.authToken = 'your_oauth2_access_token';

  // The signature base string constructed above is valid if we send this POST to "http://localhost:8080/verifysignature"
  // Normally, you'll send your POST to some api.ebay.com endpoint.
  final url = 'http://localhost:8080/verifysignature';

  final jsonStr = sbBody.getAsString();
  final resp = CkHttpResponse();
  try {
    http.httpStr('POST', 'http://localhost:8080/verifysignature', jsonStr, 'utf-8', 'application/json', resp);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  print('Response status code: ${resp.statusCode}');
  print('Response body:');
  print(resp.bodyStr);
}