Skip to content

Message Authentication

To collect statistics when using Dynamic Pages and to perform secure payment notifications the class MessageAuthentication must be implemented. Implementation examples are in NodeJS, C#, Java, and PHP.

Implementation

Dynamic page tokens shows examples of how to use this class.

const crypto = require('crypto');

module.exports = (privateKey) => {
    if (!privateKey || privateKey.length === 0) {
        throw 'Argument privateKey must not be null or empty.';
    }

    return {
        sign(message) {
            if (!message || message.length === 0) {
                throw 'Argument message must not be null or empty.';
            }
            return crypto.createHmac('sha256', privateKey).update(message).digest('hex');
        }
    }
};
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Apptus.ESales.Connector
{
    public class MessageAuthentication
    {
        private readonly string _privateKey;

        /// <summary>
        /// Creates a new instance with a specific private key, that can then be used to sign messages.
        /// </summary>
        /// <param name="privateKey">A private key that will be used as a secret in the signature. Must not be null or empty.</param>
        /// <exception cref="ArgumentException">If privateKey is null or empty.</exception>
        public MessageAuthentication(string privateKey)
        {
            if (string.IsNullOrEmpty(privateKey))
            {
                throw new ArgumentException("Argument privateKey must not be null or empty.", "privateKey");
            }
            _privateKey = privateKey;
        }

        /// <summary>
        /// Signs a message by combining it with a private key, used for prevention of unauthorised changes of the message.
        /// </summary>
        /// <param name="message">The message that should be signed. Must not be null or empty.</param>
        /// <exception cref="ArgumentException">If message is null or empty.</exception>
        /// <returns>A string token in hex format.</returns>
        public string Sign(string message)
        {
            return HmacSha256(message);
        }

        private string HmacSha256(string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                throw new ArgumentException("Argument message must not be null or empty.", "message");
            }
            using (var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(_privateKey)))
            {
                return hmacSha256
                    .ComputeHash(Encoding.UTF8.GetBytes(message))
                    .Aggregate(new StringBuilder(), (sb, b) => sb.AppendFormat("{0:x2}", b))
                    .ToString();
            }
        }
    }
}
package com.apptus.esales.connector;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
 * A class that is used for signing messages.
 */
public class MessageAuthentication {

    private final String privateKey;

    /**
     * Creates a new instance with a specific private key, that can then be used to sign messages.
     * @param privateKey A private key that will be used as a secret in the signature. Must not be null or empty.
     * @throws IllegalArgumentException If privateKey is null or empty.
     */
    public MessageAuthentication(String privateKey) {
        if (privateKey == null || privateKey.length() == 0) {
            throw new IllegalArgumentException("Argument privateKey must not be null or empty.");
        }
        this.privateKey = privateKey;
    }

    /**
     * Signs a message by combining it with a private key, used for prevention of unauthorised changes of the message.
     * @param message The message that should be signed. Must not be null or empty.
     * @return A string token in hex format.
     * @throws IllegalArgumentException If message is null or empty.
     */
    public String sign(String message) {
        return hmacSha256(message);
    }

    private String hmacSha256(String message) {
        if (message == null || message.length() == 0) {
            throw new IllegalArgumentException("Argument message must not be null or empty.");
        }

        Mac hmacSHA256;
        final String signingAlgorithm = "HmacSHA256";
        try {
            hmacSHA256 = Mac.getInstance(signingAlgorithm);
        } catch (NoSuchAlgorithmException e) {
            // This should not happen.
            throw new RuntimeException(e);
        }

        try {
            hmacSHA256.init(new SecretKeySpec(privateKey.getBytes(StandardCharsets.UTF_8), signingAlgorithm));
        } catch (InvalidKeyException e) {
            // This should not happen, currently only an internal argument check that will not happen in the hmac sha256 case.
            throw new RuntimeException(e);
        }
        return toHexString(hmacSHA256.doFinal(message.getBytes(StandardCharsets.UTF_8)));
    }

    static String toHexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            hexString.append(String.format(Locale.ROOT, "%02x", b));
        }
        return hexString.toString();
    }
}
<?php

namespace Apptus\ESales\Connector;

/**
 * A class that is used for signing messages.
 */
class MessageAuthentication {
    private $privateKey;

    /**
     * Creates a new instance with a specific private key, that can then be used to sign messages.
     * @param string $privateKey A private key that will be used as a secret in the signature. Must not be null.
     * @throws \InvalidArgumentException If privateKey is null or empty.
     */
    public function __construct($privateKey)
    {
        if (!isset($privateKey) || strlen($privateKey) == 0) {
            throw new \InvalidArgumentException('Argument $privateKey must not be null or empty.');
        }
        $this->privateKey = $privateKey;
    }

    /**
     * Signs a message by combining it with a private key, used for prevention of unauthorised changes of the message.
     * @param string $message The message that should be signed. Must not be null or empty.
     * @return string A string token in hex format.
     * @throws \InvalidArgumentException If message is null or empty.
     */
    public function sign($message) {
        if (!isset($message) || strlen($message) == 0) {
            throw new \InvalidArgumentException('Argument $message must not be null or empty.');
        }
        return hash_hmac('sha256', $message, $this->privateKey);
    }
}
×