As the sixth step you must compose the Authorization
header that must be sent in the current request.
It will be containing the previously composed strings and it's required in order to be authenticated with your shop.
This header must:
- Contains the KeyId that you obtained earlier .
- Specify that the RSA algorithm used for signing is
rsa-sha256
. - List the headers that were used when creating the Message in the correct order.
- Include the signature you created in a previous step.
Here's an example of what the Authorization
header might look like:
Authorization: Signature keyId="{keyId}", algorithm="rsa-sha256", headers="(request-target) host date digest", signature="{signature}"
Consider {keyId}
and {signature}
as placeholders for the previously generated strings.
POST /wally-services/protocol/tests/signature HTTP/1.1
Host: staging.authservices.satispay.com
Date: Mon, 18 Mar 2019 15:10:24 +0000
Content-Type: application/json
Content-Length: 123
Digest: SHA-256=ZML76UQPYzw5yDTmhySnU1S8nmqGde/jhqOG5rpfVSI=
{
"flow": "MATCH_CODE",
"amount_unit": 100,
"currency": "EUR"
}
Authorization: Signature keyId="4ekqhmf77q95deciis2frre12el393rteletbrg4rffqri3n58lsjsvf6uph934o7vr69r93iu4ifc3tkeidlg5fhoogo3grmh99lr2g94a6aerbf56m48og47e6vnbfu13rf1vvj3l4b3mn3qd2ttoc4a8hh2jgb589s59d56tdmp7dkuobesvfmnnpf8cmg7646do5", algorithm="rsa-sha256", headers="(request-target) host date digest", signature="C5yynRxJQG2VNdsH8yuGwgribKt1yzym8lYvTAwxFmjEf7akYgLeIGOkdZo5vE/oB7O7+kNgqHxPp9OKrs0XxGTBNNAOBPd0ELsptjuscWtF5dq/S4e8RjQvUcStJ6YOpwV/KyHwE1ovA1otrLpbxuUfqmNES65lRtYq6uuGinCJ+4mYnwrg9c6vuIJ/1b8VKi27PNpcJl4mwPg3hJ071T7Z2iolQRxDPN1ujQdKtUgudOIVLXiqQCPQKEaQQRvXkmh9fBH71fOsTPjvOP3q0XJp7tDPQF1K6MbF0RA6RehbuJ5nyBAOMWrk9r/+XrgC5zN3QmOtvrwmH2ko3du64A=="
Code sample 4/4
$bodyObject = [
'flow' => 'MATCH_CODE',
'amount_unit' => 100,
'currency' => 'EUR'
];
$body = json_encode($bodyObject);
echo "body:\n";
echo $body . "\n";
$digest = "SHA-256=" . base64_encode(hash("sha256", $body, true));
echo "\ndigest:\n";
echo $digest . "\n";
$date = date('r');
echo "\ndate:\n";
echo $date . "\n";
$message = "(request-target): post /g_business/v1/payments
host: staging.authservices.satispay.com
date: $date
digest: $digest";
echo "\nmessage:\n";
echo $message . "\n";
$privateKey = file_get_contents('private.pem'); // your private key
echo "\nprivate.pem:\n";
echo $privateKey . "\n";
openssl_sign($message, $signatureRaw, $privateKey, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signatureRaw);
echo "\nsignature:\n";
echo $signature . "\n";
$keyId = file_get_contents('KeyId.txt'); // your KeyId
$authorization = "Signature keyId=\"$keyId\", algorithm=\"rsa-sha256\", headers=\"(request-target) host date digest\", signature=\"$signature\"";
echo "\nauthorization:\n";
echo $authorization . "\n";
// send an HTTP request to the /g_business/v1/payments URL
// the body must be equals to the $body variable
// the $date variable must be sent as "date" header
// the $authorization variable must be sent as "authorization" header
const crypto = require('crypto');
const fs = require('fs');
const bodyObject = {
flow: 'MATCH_CODE',
amount_unit: 100,
currency: 'EUR'
};
const body = JSON.stringify(bodyObject);
console.log("\nbody:");
console.log(body);
const digest = "SHA-256=" + crypto.createHash('sha256').update(body).digest('base64');
console.log("\ndigest:");
console.log(digest);
const date = new Date().toUTCString();
console.log("\ndate:");
console.log(date);
const message = "(request-target): post /g_business/v1/payments\n" +
"host: staging.authservices.satispay.com\n" +
"date: " + date + "\n" +
"digest: " + digest;
console.log("\nmessage:");
console.log(message);
const privateKey = fs.readFileSync('private.pem', 'utf-8');
console.log("\nprivate.pem:");
console.log(privateKey);
const sign = crypto.createSign('RSA-SHA256');
sign.update(message);
const signatureRaw = sign.sign(privateKey, 'base64');
const signature = Buffer.from(signatureRaw, 'base64').toString('base64');
console.log("\nsignature:");
console.log(signature);
const keyId = fs.readFileSync('KeyId.txt', 'utf-8');
const authorization = "Signature keyId=\"" + keyId.trim() + "\", algorithm=\"rsa-sha256\", headers=\"(request-target) host date digest\", signature=\"" + signature + "\"";
console.log("\nauthorization:");
console.log(authorization);
// send an HTTP request to the /g_business/v1/payments URL
// the body must be equals to the $body variable
// the date variable must be sent as "date" header
// the authorization variable must be sent as "authorization" header
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONObject;
public class Satispay {
public static void main(String[] args) {
JSONObject bodyObject = new JSONObject()
.put("flow", "MATCH_CODE")
.put("amount_unit", 100)
.put("currency", "EUR");
String body = bodyObject.toString();
System.out.println("body:");
System.out.println(body);
String digest = createDigest(body);
System.out.println();
System.out.println("digest:");
System.out.println(digest);
SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
String date = sdf.format(new Date());
System.out.println();
System.out.println("date:");
System.out.println(date);
String message = "(request-target): post /g_business/v1/payments\n" +
"host: staging.authservices.satispay.com\n" +
"date: " + date + "\n" +
"digest: " + digest;
System.out.println();
System.out.println("message:");
System.out.println(message);
String privateKey = readPemKey("private.pem"); // your private key
System.out.println();
System.out.println("private.pem:");
System.out.println(privateKey);
String signature = signData(message, privateKey);
System.out.println();
System.out.println("signature:");
System.out.println(signature);
String keyId = readFile("KeyId.txt");
String authorization = String.format("Signature keyId=\"%s\", algorithm=\"rsa-sha256\", headers=\"(request-target) host date digest\", signature=\"%s\"", keyId, signature);
System.out.println();
System.out.println("authorization:");
System.out.println(authorization);
// send an HTTP request to the /g_business/v1/payments URL
// the body must be equals to the body variable
// the date variable must be sent as "date" header
// the authorization variable must be sent as "authorization" header
}
private static String createDigest(String body) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = messageDigest.digest(body.getBytes("UTF-8"));
return "SHA-256=" + Base64.getEncoder().encodeToString(hashBytes);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
public static String signData(String message, String base64PrivateKey) {
try {
byte[] privateKeyBytes = Base64.getDecoder().decode(base64PrivateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(message.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = signature.sign();
return Base64.getEncoder().encodeToString(signatureBytes);
} catch (
NoSuchAlgorithmException |
InvalidKeySpecException |
InvalidKeyException |
SignatureException e
) {
e.printStackTrace();
System.exit(1);
}
return null;
}
private static String readPemKey(String filePath) {
try {
String pemText = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
Pattern pattern = Pattern.compile("-----(?:.*?)-----([^-]*)-----(?:.*?)-----", Pattern.DOTALL);
Matcher matcher = pattern.matcher(pemText);
String base64Key = pemText;
if (matcher.find()) {
base64Key = matcher.group(1).replace("\r", "").replace("\n", "");;
}
return base64Key;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
private static String readFile(String filePath) {
try {
return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
class Satispay
{
static void Main(string[] args)
{
var bodyObject = new Dictionary<string, object>
{
{ "flow", "MATCH_CODE" },
{ "amount_unit", 100 },
{ "currency", "EUR" }
};
var body = JsonSerializer.Serialize(bodyObject);
Console.WriteLine("body:");
Console.WriteLine(body);
var digest = createDigest(body);
Console.WriteLine();
Console.WriteLine("digest:");
Console.WriteLine(digest);
string date = DateTime.UtcNow.ToString("r");
Console.WriteLine();
Console.WriteLine("date:");
Console.WriteLine(date);
string message = "(request-target): post /g_business/v1/payments\n" +
"host: staging.authservices.satispay.com\n" +
$"date: {date}\n" +
$"digest: {digest}";
Console.WriteLine();
Console.WriteLine("message:");
Console.WriteLine(message);
string privateKey = readPemKey("private.pem"); // your private key
Console.WriteLine();
Console.WriteLine("private.pem:");
Console.WriteLine(privateKey);
string signature = signData(message, privateKey);
Console.WriteLine();
Console.WriteLine("signature:");
Console.WriteLine(signature);
string keyId = readFile("KeyId.txt"); // your KeyId
string authorization = $"Authorization: Signature keyId=\"{keyId}\", algorithm=\"rsa-sha256\", headers=\"(request-target) host date digest\", signature=\"{signature}\"";
Console.WriteLine();
Console.WriteLine("authorization:");
Console.WriteLine(authorization);
// send an HTTP request to the /g_business/v1/payments URL
// the body must be equals to the body variable
// the date variable must be sent as "date" header
// the authorization variable must be sent as "authorization" header
}
static string createDigest(string body)
{
var sha256 = SHA256.Create();
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(body));
return "SHA-256=" + Convert.ToBase64String(hashBytes);
}
static string signData(string data, string privateKey)
{
byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
using (var rsa = RSA.Create())
{
rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _);
var sha256 = SHA256.Create();
byte[] hash = sha256.ComputeHash(dataBytes);
byte[] signatureBytes = rsa.SignHash(hash, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
string signature = Convert.ToBase64String(signatureBytes);
return signature;
}
}
static string readPemKey(string filePath)
{
string pemText = File.ReadAllText(filePath);
string base64Key = pemText.Replace("-----BEGIN PRIVATE KEY-----", "")
.Replace("-----END PRIVATE KEY-----", "")
.Replace("\r", "")
.Replace("\n", "");
return base64Key;
}
static string readFile(string filePath)
{
return File.ReadAllText(filePath);
}
}
import json
import hashlib
import base64
import time
import datetime
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
body_object = {
'flow': 'MATCH_CODE',
'amount_unit': 100,
'currency': 'EUR'
}
body = json.dumps(body_object)
print("body:")
print(body)
digest = "SHA-256=" + base64.b64encode(hashlib.sha256(body.encode()).digest()).decode()
print()
print("digest:")
print(digest)
date = datetime.datetime.now(datetime.timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
print()
print("date:")
print(date)
message = "(request-target): post /g_business/v1/payments\n\
host: staging.authservices.satispay.com\n\
date: " + date + "\n\
digest: " + digest
print()
print("message:")
print(message)
with open('private.pem', 'rb') as private_key_file:
private_key_file = private_key_file.read()
private_key = serialization.load_pem_private_key(
private_key_file,
password=None,
backend=default_backend()
)
print()
print("private.pem:")
print(private_key_file.decode())
signature = private_key.sign(
message.encode(),
padding.PKCS1v15(),
hashes.SHA256()
)
signature = base64.b64encode(signature).decode()
print()
print("signature:")
print(signature)
with open('KeyId.txt', 'r') as key_id_file:
key_id = key_id_file.read().strip()
authorization = f'Signature keyId="{key_id}", algorithm="rsa-sha256", headers="(request-target) host date digest", signature="{signature}"'
print()
print("authorization:")
print(authorization)
# Send an HTTP request to the /g_business/v1/payments URL
# The body must be equal to the 'body' variable
# The 'date' variable must be sent as the "date" header
# The 'authorization' variable must be sent as the "authorization" header
#!/bin/bash
body='{
"flow": "MATCH_CODE",
"amount_unit": 100,
"currency": "EUR"
}'
echo "body:"
printf "%s" "$body"
digest="SHA-256=$(printf "%s" "$body" | openssl dgst -sha256 -binary | base64 -w 0)"
echo "\n"
echo "\ndigest:"
echo "$digest"
date=$(date -R)
echo "\ndate:"
echo "$date"
message="(request-target): post /g_business/v1/payments"$'\n'
message+="host: staging.authservices.satispay.com"$'\n'
message+="date: $date"$'\n'
message+="digest: $digest"
echo "\nmessage:"
echo "$message"
private_key=$(cat private.pem)
echo "\nprivate.pem:"
echo "$private_key"
signature=$(printf "%s" "$message" | openssl dgst -sign private.pem -sha256 -binary | base64 -w 0)
echo "\nsignature:"
echo "$signature"
keyId=$(cat KeyId.txt)
authorization="Signature keyId=\"$keyId\", algorithm=\"rsa-sha256\", headers=\"(request-target) host date digest\", signature=\"$signature\""
echo "\nauthorization:"
echo "$authorization"
# send an HTTP request to the /g_business/v1/payments URL
# the body must be equal to the $body variable
# the $date variable must be sent as "date" header
# the $authorization variable must be sent as "authorization" header