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#, and Java.

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();
    }
}
×
Copyright

This online publication is intellectual property of Voyado Lund AB. Its contents can be duplicated in part or whole, provided that a copyright label is visibly located on each copy and the copy is used in conjunction with the product described within this document.

All information found in these documents has been compiled with utmost attention to detail. However, this does not guarantee complete accuracy. Neither Voyado Lund AB nor the authors shall be held liable for possible errors or the consequences thereof.

Software and hardware descriptions cited in these documents might be registered trademarks. All trade names are subject to copyright restrictions and may be registered trademarks. Voyado Lund AB essentially adheres to the manufacturer’s spelling. Names of products and trademarks appearing in this document, with or without specific notation, are likewise subject to trademark and trade protection laws and may thus fall under copyright restrictions.

CLOSE