Skip to main content

Authentication

Authentication is implemented by signing a request using both HMAC and ECDSA algorithms.

For authentication use Authorization Header like:

Authorization: s1mpl signature <identity> <alg> <data>
  • identity - user/service (provided be vendor)
  • alg - signature algorithm (for project es256 or hmac-sha-256)
  • data - byte array of signature data (base64)

HMAC-SHA-256

Generate Secret Key

Run this command to get random bytes:

openssl rand -base64 32

You will receive such result:

PHshl72MfvvfM5Kmr6P/m9RCIxF+mCorXf4wlT3uMno=

You should share this key with us and use it to sign your authentication requests.

Signing examples

private static readonly byte[] HmacKey = Convert.FromBase64String(@"PHshl72MfvvfM5Kmr6P/m9RCIxF+mCorXf4wlT3uMno=");

private static async Task Main(string[] args)
{
var client = new HttpClient();

var url = "https://customer.s1mpl.com/api/v3/customers/123/offers?language=ru";

var request = new HttpRequestMessage(HttpMethod.Get, url);

var sign = CreateHmacSha256Signature();

request.Headers.Add("Authorization", $"s1mpl signature some-service hmac-sha-256 { Convert.ToBase64String(sign) }");

var response = await client.SendAsync(request);

Console.ReadLine();
}

private static byte[] CreateHmacSha256Signature()
{
var data = BitConverter.GetBytes(DateTime.UtcNow.Ticks)
.Concat(Guid.NewGuid().ToByteArray())
.ToArray();

var signature = HMACSHA256.HashData(HmacKey, data);

return data.Concat(signature).ToArray();
}

ES256

Generate Private and Public Keys

Your private key is used to sign your authentication requests. Run this command to create your private key:

openssl ecparam -name prime256v1 -genkey -out private.pem

Use private key to generate a public key:

openssl ec -in private.pem -pubout -out public.pem

The result of these commands will be two files:

private.pem example

-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICANhwl1a8C7PDQE+BBBY1nr6RPIBxcp461EyBU7k5WzoAoGCCqGSM49
AwEHoUQDQgAEdVgfFzlM6jT2okGwtM65Cl091OUTA7+bTj2nRmyIsU33TQeq15pn
hTz7nk3rJK+p/hCsk/mHdEAMGsb/4cKqkA==
-----END EC PRIVATE KEY-----

You should leave only this part:

MHcCAQEEICANhwl1a8C7PDQE+BBBY1nr6RPIBxcp461EyBU7k5WzoAoGCCqGSM49
AwEHoUQDQgAEdVgfFzlM6jT2okGwtM65Cl091OUTA7+bTj2nRmyIsU33TQeq15pn
hTz7nk3rJK+p/hCsk/mHdEAMGsb/4cKqkA==

public.pem example

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdVgfFzlM6jT2okGwtM65Cl091OUT
A7+bTj2nRmyIsU33TQeq15pnhTz7nk3rJK+p/hCsk/mHdEAMGsb/4cKqkA==
-----END PUBLIC KEY-----

Signing examples

private static readonly byte[] PrivateKey = Convert.FromBase64String(@"MHcCAQEEICANhwl1a8C7PDQE+BBBY1nr6RPIBxcp461EyBU7k5WzoAoGCCqGSM49AwEHoUQDQgAEdVgfFzlM6jT2okGwtM65Cl091OUTA7+bTj2nRmyIsU33TQeq15pnhTz7nk3rJK+p/hCsk/mHdEAMGsb/4cKqkA==");

private static async Task Main(string[] args)
{
var client = new HttpClient();

var url = "https://customer.s1mpl.com/api/v3/customers/123/offers?language=ru";;

var request = new HttpRequestMessage(HttpMethod.Get, url);

var sign = CreateSignature();

request.Headers.Add("Authorization", $"s1mpl signature some-service es256 { Convert.ToBase64String(sign) }");

var response = await client.SendAsync(request);

Console.ReadLine();
}

private static byte[] CreateSignature()
{
var alg = ECDsa.Create();

if (alg == null)
throw new InvalidOperationException("No signature algorithm implementation available");

var signingData = BitConverter.GetBytes(DateTime.UtcNow.Ticks)
.Concat(Guid.NewGuid().ToByteArray())
.ToArray();

alg.ImportECPrivateKey(PrivateKey, out _);

var signature = alg.SignData(signingData, HashAlgorithmName.SHA256);

return signingData.Concat(signature).ToArray();
}