package de.bornemisza.security;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

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

public abstract class HashProvider {

    private static final String algorithm = "HmacSHA256";
    private Mac mac;

    public HashProvider() {
    }

    protected abstract char[] getServerSecret();

    @PostConstruct
    protected void init() {
        try {
            SecretKeySpec key = new SecretKeySpec(toBytes(getServerSecret()), algorithm);
            mac = Mac.getInstance(algorithm);
            mac.init(key);
        }
        catch (InvalidKeyException | NoSuchAlgorithmException ex) {
            throw new RuntimeException("Problem generating secret key", ex);
        }
    }

    public String hmacDigest(String msg) {
        try {
            byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
            return createHexString(bytes);
        }
        catch (UnsupportedEncodingException ex) {
            throw new RuntimeException("Problem generating Hash", ex);
        }
    }

    private String createHexString(byte[] bytes) {
        StringBuilder hash = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                hash.append('0');
            }
            hash.append(hex);
        }
        return hash.toString();
    }

    private byte[] toBytes(char[] chars) {
        CharBuffer charBuffer = CharBuffer.wrap(chars);
        ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
        byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
                byteBuffer.position(), byteBuffer.limit());
        Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
        Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
        return bytes;
    }

}

@@ -636,32 +636,85 @@
 %7B%0A        try %7B%0A
+            char%5B%5D serverSecret = getServerSecret();%0A
             Secr
@@ -755,20 +755,17 @@
 toBytes(
-getS
+s
 erverSec
@@ -767,18 +767,16 @@
 erSecret
-()
 ), algor
@@ -774,32 +774,76 @@
 t), algorithm);%0A
+            Arrays.fill(serverSecret, '*');%0A
             mac 

mask password