org.sentilo.common.rest.hmac.HMACBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.sentilo.common.rest.hmac.HMACBuilder.java

Source

/*
 * Sentilo
 * 
 * Copyright (C) 2013 Institut Municipal dInformtica, Ajuntament de Barcelona.
 * 
 * This program is licensed and may be used, modified and redistributed under the terms of the
 * European Public License (EUPL), either version 1.1 or (at your option) any later version as soon
 * as they are approved by the European Commission.
 * 
 * Alternatively, you may redistribute and/or modify this program under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied.
 * 
 * See the licenses for the specific language governing permissions, limitations and more details.
 * 
 * You should have received a copy of the EUPL1.1 and the LGPLv3 licenses along with this program;
 * if not, you may find them at:
 * 
 * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl http://www.gnu.org/licenses/ and
 * https://www.gnu.org/licenses/lgpl.txt
 */
package org.sentilo.common.rest.hmac;

import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

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

import org.apache.commons.codec.binary.Base64;
import org.apache.http.entity.ContentType;

/**
 * Utility class to build an HMAC value from request content to use as header in notification
 * callbacks.
 * 
 */
public abstract class HMACBuilder {

    private final static String DIGEST_ALGORITHM = "MD5";
    private final static String MAC_ALGORITHM = "HmacSHA512";
    private final static String HTTP_VERB = "POST";
    private final static String TOKEN = "\n";

    public static String buildHeader(final String body, final String endpoint, final String secret,
            final String currentDate) throws GeneralSecurityException {
        final String contentMd5 = calculateMD5(body);
        final String toSign = getContentToSign(HTTP_VERB, contentMd5, ContentType.APPLICATION_JSON.getMimeType(),
                currentDate, endpoint);
        return calculateHMAC(secret, toSign);
    }

    private static String getContentToSign(final String... values) {
        final StringBuilder content = new StringBuilder();
        boolean first = true;

        for (final String value : values) {
            if (!first) {
                content.append(TOKEN);
            }

            content.append(value);

            first = false;
        }

        return content.toString();
    }

    private static String calculateHMAC(final String secret, final String data) throws GeneralSecurityException {
        final SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), MAC_ALGORITHM);

        final Mac mac = Mac.getInstance(MAC_ALGORITHM);
        mac.init(signingKey);

        final byte[] rawHmac = mac.doFinal(data.getBytes());
        return new String(Base64.encodeBase64(rawHmac));
    }

    private static String calculateMD5(final String contentToEncode) throws NoSuchAlgorithmException {
        final MessageDigest digest = MessageDigest.getInstance(DIGEST_ALGORITHM);
        digest.update(contentToEncode.getBytes());
        return new String(Base64.encodeBase64(digest.digest()));
    }

    private HMACBuilder() {
        throw new AssertionError();
    }

}