All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.fitko.fitconnect.core.crypto.HashService Maven / Gradle / Ivy

Go to download

Library that provides client access to the FIT-Connect api-endpoints for sending, subscribing and routing

There is a newer version: 2.3.5
Show newest version
package dev.fitko.fitconnect.core.crypto;

import dev.fitko.fitconnect.api.exceptions.internal.EncryptionException;
import dev.fitko.fitconnect.api.services.crypto.MessageDigestService;

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

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static dev.fitko.fitconnect.core.crypto.constants.CryptoConstants.DEFAULT_HASH_ALGORITHM;
import static dev.fitko.fitconnect.core.crypto.constants.CryptoConstants.DEFAULT_HMAC_ALGORITHM;

public class HashService implements MessageDigestService {

    @Override
    public byte[] createHash(final byte[] data) {
        try {
            final var messageDigest = MessageDigest.getInstance(DEFAULT_HASH_ALGORITHM);
            return messageDigest.digest(data);
        } catch (final NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public byte[] createHash(final InputStream inputStream) {
        try {
            final var messageDigest = MessageDigest.getInstance(DEFAULT_HASH_ALGORITHM);
            final byte[] buffer = new byte[8192];
            for (int read; (read = inputStream.read(buffer)) != -1; ) {
                messageDigest.update(buffer, 0, read);
            }
            return messageDigest.digest();
        } catch (final NoSuchAlgorithmException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean verify(final byte[] originalHash, final byte[] data) {
        final byte[] newHash = createHash(data);
        return compareHashes(originalHash, newHash);
    }

    @Override
    public boolean verify(final byte[] originalHash, final InputStream data) {
        final byte[] newHash = createHash(data);
        return compareHashes(originalHash, newHash);
    }

    @Override
    public String toHexString(final byte[] hash) {
        final StringBuilder hexStringBuffer = new StringBuilder();
        for (final byte b : hash) {
            hexStringBuffer.append(byteToHex(b));
        }
        return hexStringBuffer.toString();
    }

    @Override
    public byte[] fromHexString(final String hexString) {
        if (hexString.length() % 2 == 1) {
            throw new IllegalArgumentException("Invalid hexadecimal String.");
        }

        final byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
        }
        return bytes;
    }

    @Override
    public String calculateHMAC(final String data, final String key) {
        try {
            final String hmacAlgorithm = DEFAULT_HMAC_ALGORITHM;
            final SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), hmacAlgorithm);
            final Mac mac = Mac.getInstance(hmacAlgorithm);
            mac.init(secretKeySpec);
            return toHexString(mac.doFinal(data.getBytes()));
        } catch (final NoSuchAlgorithmException | InvalidKeyException e) {
            throw new EncryptionException("Calculation of HMAC failed.", e);
        }
    }

    private byte hexToByte(final String hexString) {
        final int firstDigit = toDigit(hexString.charAt(0));
        final int secondDigit = toDigit(hexString.charAt(1));
        return (byte) ((firstDigit << 4) + secondDigit);
    }

    private int toDigit(final char hexChar) {
        final int digit = Character.digit(hexChar, 16);
        if (digit == -1) {
            throw new IllegalArgumentException("Invalid Hexadecimal Character: " + hexChar);
        }
        return digit;
    }

    private String byteToHex(final byte num) {
        final char[] hexDigits = new char[2];
        hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
        hexDigits[1] = Character.forDigit((num & 0xF), 16);
        return new String(hexDigits);
    }

    private boolean compareHashes(final byte[] originalHash, final byte[] comparisonHash) {
        int diff = originalHash.length ^ comparisonHash.length;
        for (int i = 0; i < originalHash.length && i < comparisonHash.length; i++) {
            diff |= originalHash[i] ^ comparisonHash[i];
        }
        return diff == 0;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy