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.