Implemented HMAC authentication in RecorderServlet
This commit is contained in:
parent
8c7385229f
commit
d62bba5599
|
@ -71,7 +71,7 @@ public class Config {
|
|||
|
||||
public void save() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder().build();
|
||||
JsonAdapter<Settings> adapter = moshi.adapter(Settings.class);
|
||||
JsonAdapter<Settings> adapter = moshi.adapter(Settings.class).indent(" ");
|
||||
String json = adapter.toJson(settings);
|
||||
File configDir = OS.getConfigDir();
|
||||
File configFile = new File(configDir, filename);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package ctbrec;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Hmac {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(Hmac.class);
|
||||
|
||||
public static byte[] generateKey() {
|
||||
LOG.debug("Generating key");
|
||||
SecureRandom random = new SecureRandom();
|
||||
byte[] key = new byte[32];
|
||||
random.nextBytes(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
public static String calculate(String msg, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException, UnsupportedEncodingException {
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
|
||||
mac.init(keySpec);
|
||||
byte[] result = mac.doFinal(msg.getBytes("UTF-8"));
|
||||
String hmac = bytesToHex(result);
|
||||
return hmac;
|
||||
}
|
||||
|
||||
public static boolean validate(String msg, byte[] key, String hmacToCheck) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {
|
||||
return Hmac.calculate(msg, key).equals(hmacToCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array to a string
|
||||
*
|
||||
* @param hash
|
||||
* @return string
|
||||
*/
|
||||
static String bytesToHex(byte[] hash) {
|
||||
StringBuffer hexString = new StringBuffer();
|
||||
for (int i = 0; i < hash.length; i++) {
|
||||
String hex = Integer.toHexString(0xff & hash[i]);
|
||||
if (hex.length() == 1)
|
||||
hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
}
|
|
@ -16,4 +16,6 @@ public class Settings {
|
|||
public String lastDownloadDir = "";
|
||||
public List<Model> models = new ArrayList<Model>();
|
||||
public boolean determineResolution = false;
|
||||
public boolean requireAuthentication = false;
|
||||
public byte[] key = null;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@ package ctbrec.recorder.server;
|
|||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -21,6 +24,8 @@ import org.slf4j.LoggerFactory;
|
|||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Hmac;
|
||||
import ctbrec.InstantJsonAdapter;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
|
@ -43,6 +48,14 @@ public class RecorderServlet extends HttpServlet {
|
|||
|
||||
try {
|
||||
String json = body(req);
|
||||
boolean isRequestAuthenticated = checkAuthentication(req, json);
|
||||
if(!isRequestAuthenticated) {
|
||||
resp.setStatus(SC_UNAUTHORIZED);
|
||||
String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||
resp.getWriter().write(response);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("Request: {}", json);
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(Instant.class, new InstantJsonAdapter())
|
||||
|
@ -116,6 +129,21 @@ public class RecorderServlet extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean checkAuthentication(HttpServletRequest req, String body) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException {
|
||||
boolean authenticated = false;
|
||||
if(Config.getInstance().getSettings().key != null) {
|
||||
if(req.getHeader("CTBREC-HMAC") == null) {
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
byte[] key = Config.getInstance().getSettings().key;
|
||||
authenticated = Hmac.validate(body, key, req.getHeader("CTBREC-HMAC"));
|
||||
} else {
|
||||
authenticated = true;
|
||||
}
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
private String body(HttpServletRequest req) throws IOException {
|
||||
StringBuilder body = new StringBuilder();
|
||||
BufferedReader br = req.getReader();
|
||||
|
|
Loading…
Reference in New Issue