Signature is the signed String created at the previous step

As the fifth step, you need to sign the previously created Message with your private key .
The signature should be signed using the rsa-sha256 algorithm and should be encoded in Base64.

(request-target): post /wally-services/protocol/tests/signature
host: staging.authservices.satispay.com
date: Mon, 18 Mar 2019 15:10:24 +0000
digest: SHA-256=ZML76UQPYzw5yDTmhySnU1S8nmqGde/jhqOG5rpfVSI=
XyuV4SB3TnwXsPj5d9m/3Ju+QvegeuzDp23IpHEJ18W7gVIVUFBBraDGNSTYk4ohJfx0xsRj2B14PDLZu+z7SVeDuUQVk5mJNZnvf9lbQ0MN1W0qT/lWmsLAusDZ2TabxiDwahPNjA9ZpQOGo6sjoAGK8TSejMxffrQI0EV4mYo6KAl+sk4DGjV7GM7F/imgsw17ji1x8HpRO72slgbOPPHdjADDmGUEgSd0/MhcCHbHH6XIq+VkGSkQ83xNe1t85gQtVYh96oj6q7qz/qEhNbbGj50LhdYGv2tTtUNXU+Zk5NMNIIXwk+OmCq8mK7M/6Dmfd/prklsS7PrCCnRDnpdnRVJeFRjJMnKBc8A/ITS7jjP6vU7GZ9ltmPjPKt6/GgnZWTYjcsnqcCifyoDJt0egLimkkp8HyLWsDke08DAJHR0ylKbYc/kVwabhlZGzkDMb4DyMi4op6xp5+k8pQb6IXuI4YzraPUOblfRi/mWYUDUUfR0GPfkPIht2AjNbdvZ+bbvhsoFY57oofBQaXIcYbecQPH6la4bPADJCM3R+uFeMuMtmg7GUTl7uOOSIEs1VJRhJaBkOsuTIs3d/gk6YGOdff+1MXaopoiBxoA0+1g/9g+jVA3xQnTk9RfRzb8WHB1LkqbATHwt5rQSNQKSpvz/wCejlb566P2Ffc8w=

🚧

Beware

Please note that the Message must be signed, not encrypted.


Code sample 3/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";
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);
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);
    }

    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);
    }

    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)
#!/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"

Signature checker

We've designed this tool for you to validate the signature you've generated.
Please make sure that your output matches the result generated by this tool.

🚧

Beware

Ensure that the output provided by this tool matches your implementation.
If there are differences, it's likely a signature issue.