Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 5c62208

Browse files
author
Dan Richelson
committed
Add secure mode hash method
1 parent 462e8ab commit 5c62208

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/main/java/com/launchdarkly/client/LDClient.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@
44
import com.google.common.annotations.VisibleForTesting;
55
import com.google.gson.JsonElement;
66
import com.google.gson.JsonPrimitive;
7+
import org.apache.commons.codec.binary.Hex;
78
import org.apache.http.annotation.ThreadSafe;
89
import org.slf4j.Logger;
910
import org.slf4j.LoggerFactory;
1011

12+
import javax.crypto.Mac;
13+
import javax.crypto.spec.SecretKeySpec;
1114
import java.io.Closeable;
1215
import java.io.IOException;
16+
import java.io.UnsupportedEncodingException;
1317
import java.net.URL;
18+
import java.security.InvalidKeyException;
19+
import java.security.NoSuchAlgorithmException;
1420
import java.util.HashMap;
1521
import java.util.Map;
1622
import java.util.concurrent.Future;
@@ -26,11 +32,14 @@
2632
@ThreadSafe
2733
public class LDClient implements Closeable {
2834
private static final Logger logger = LoggerFactory.getLogger(LDClient.class);
35+
private static final String HMAC_ALGORITHM = "HmacSHA256";
36+
protected static final String CLIENT_VERSION = getClientVersion();
37+
2938
private final LDConfig config;
39+
private final String apiKey;
3040
private final FeatureRequestor requestor;
3141
private final EventProcessor eventProcessor;
3242
private UpdateProcessor updateProcessor;
33-
protected static final String CLIENT_VERSION = getClientVersion();
3443

3544
/**
3645
* Creates a new client instance that connects to LaunchDarkly with the default configuration. In most
@@ -51,6 +60,7 @@ public LDClient(String apiKey) {
5160
*/
5261
public LDClient(String apiKey, LDConfig config) {
5362
this.config = config;
63+
this.apiKey = apiKey;
5464
this.requestor = createFeatureRequestor(apiKey, config);
5565
this.eventProcessor = createEventProcessor(apiKey, config);
5666

@@ -368,6 +378,25 @@ public boolean isOffline() {
368378
return config.offline;
369379
}
370380

381+
/**
382+
* For more info: <a href=https://github.com/launchdarkly/js-client#secure-mode>https://github.com/launchdarkly/js-client#secure-mode</a>
383+
* @param user The User to be hashed along with the api key
384+
* @return the hash, or null if the hash could not be calculated.
385+
*/
386+
public String secureModeHash(LDUser user) {
387+
if (user == null || user.getKeyAsString().isEmpty()) {
388+
return null;
389+
}
390+
try {
391+
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
392+
mac.init(new SecretKeySpec(apiKey.getBytes(), HMAC_ALGORITHM));
393+
return Hex.encodeHexString(mac.doFinal(user.getKeyAsString().getBytes("UTF8")));
394+
} catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException e) {
395+
logger.error("Could not generate secure mode hash", e);
396+
}
397+
return null;
398+
}
399+
371400
private static String getClientVersion() {
372401
Class clazz = LDConfig.class;
373402
String className = clazz.getSimpleName() + ".class";

src/test/java/com/launchdarkly/client/LDClientTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@ public void testPollingWait() throws Exception {
341341
verifyAll();
342342
}
343343

344+
@Test
345+
public void testSecureModeHash() {
346+
LDConfig config = new LDConfig.Builder()
347+
.offline(true)
348+
.build();
349+
LDClient client = new LDClient("secret", config);
350+
LDUser user = new LDUser.Builder("Message").build();
351+
assertEquals("aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597", client.secureModeHash(user));
352+
}
353+
344354
private void assertDefaultValueIsReturned() {
345355
boolean result = client.boolVariation("test", new LDUser("test.key"), true);
346356
assertEquals(true, result);

0 commit comments

Comments
 (0)