Support for SHA-256 (#11240)

Signed-off-by: Pawel Pieczul <pieczul@gmail.com>
This commit is contained in:
Pawel Pieczul 2021-09-17 08:40:11 +02:00 committed by GitHub
parent 30198e273a
commit 3fc7c6559c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 10 deletions

View File

@ -126,16 +126,18 @@ public abstract class LxWsSecurity {
* *
* @param string string to be hashed * @param string string to be hashed
* @param hashKeyHex hash key received from the Miniserver in hex format * @param hashKeyHex hash key received from the Miniserver in hex format
* @param sha256 if SHA-256 algorithm should be used (SHA-1 otherwise)
* @return hashed string or null if failed * @return hashed string or null if failed
*/ */
String hashString(String string, String hashKeyHex) { String hashString(String string, String hashKeyHex, boolean sha256) {
if (string == null || hashKeyHex == null) { if (string == null || hashKeyHex == null) {
return null; return null;
} }
try { try {
String alg = sha256 ? "HmacSHA256" : "HmacSHA1";
byte[] hashKeyBytes = HexUtils.hexToBytes(hashKeyHex); byte[] hashKeyBytes = HexUtils.hexToBytes(hashKeyHex);
SecretKeySpec signKey = new SecretKeySpec(hashKeyBytes, "HmacSHA1"); SecretKeySpec signKey = new SecretKeySpec(hashKeyBytes, alg);
Mac mac = Mac.getInstance("HmacSHA1"); Mac mac = Mac.getInstance(alg);
mac.init(signKey); mac.init(signKey);
byte[] rawData = mac.doFinal(string.getBytes()); byte[] rawData = mac.doFinal(string.getBytes());
return HexUtils.bytesToHex(rawData); return HexUtils.bytesToHex(rawData);

View File

@ -57,7 +57,7 @@ class LxWsSecurityHash extends LxWsSecurity {
if (!checkResponse(resp)) { if (!checkResponse(resp)) {
return false; return false;
} }
String hash = hashString(user + ":" + password, resp.getValueAsString()); String hash = hashString(user + ":" + password, resp.getValueAsString(), false);
if (hash == null) { if (hash == null) {
return setError(LxErrorCode.INTERNAL_ERROR, "Error hashing credentials."); return setError(LxErrorCode.INTERNAL_ERROR, "Error hashing credentials.");
} }

View File

@ -86,6 +86,7 @@ class LxWsSecurityToken extends LxWsSecurity {
private class LxResponseKeySalt { private class LxResponseKeySalt {
String key; String key;
String salt; String salt;
String hashAlg;
} }
/** /**
@ -148,6 +149,7 @@ class LxWsSecurityToken extends LxWsSecurity {
private int tokenRefreshRetryCount; private int tokenRefreshRetryCount;
private ScheduledFuture<?> tokenRefreshTimer; private ScheduledFuture<?> tokenRefreshTimer;
private final Lock tokenRefreshLock = new ReentrantLock(); private final Lock tokenRefreshLock = new ReentrantLock();
private boolean sha256 = false;
private final byte[] initVector = new byte[IV_LENGTH_BYTES]; private final byte[] initVector = new byte[IV_LENGTH_BYTES];
private final Logger logger = LoggerFactory.getLogger(LxWsSecurityToken.class); private final Logger logger = LoggerFactory.getLogger(LxWsSecurityToken.class);
@ -352,14 +354,14 @@ class LxWsSecurityToken extends LxWsSecurity {
} }
} }
private String hashCredentials(LxResponseKeySalt keySalt) { private String hashCredentials(LxResponseKeySalt keySalt, boolean sha256) {
try { try {
MessageDigest msgDigest = MessageDigest.getInstance("SHA-1"); MessageDigest msgDigest = MessageDigest.getInstance(sha256 ? "SHA-256" : "SHA-1");
String pwdHashStr = password + ":" + keySalt.salt; String pwdHashStr = password + ":" + keySalt.salt;
byte[] rawData = msgDigest.digest(pwdHashStr.getBytes(StandardCharsets.UTF_8)); byte[] rawData = msgDigest.digest(pwdHashStr.getBytes(StandardCharsets.UTF_8));
String pwdHash = HexUtils.bytesToHex(rawData).toUpperCase(); String pwdHash = HexUtils.bytesToHex(rawData).toUpperCase();
logger.debug("[{}] PWDHASH: {}", debugId, pwdHash); logger.debug("[{}] PWDHASH: {}", debugId, pwdHash);
return hashString(user + ":" + pwdHash, keySalt.key); return hashString(user + ":" + pwdHash, keySalt.key, sha256);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
logger.debug("[{}] Error hashing token credentials: {}", debugId, e.getMessage()); logger.debug("[{}] Error hashing token credentials: {}", debugId, e.getMessage());
return null; return null;
@ -376,10 +378,12 @@ class LxWsSecurityToken extends LxWsSecurity {
if (keySalt == null) { if (keySalt == null) {
return setError(null, "Error parsing hash key/salt json: " + resp.getValueAsString()); return setError(null, "Error parsing hash key/salt json: " + resp.getValueAsString());
} }
if ("SHA256".equals(keySalt.hashAlg)) {
sha256 = true;
}
logger.debug("[{}] Hash key: {}, salt: {}", debugId, keySalt.key, keySalt.salt); logger.debug("[{}] Hash key: {}, salt: {}", debugId, keySalt.key, keySalt.salt);
// Hash user name, password, key and salt // Hash user name, password, key and salt
String hash = hashCredentials(keySalt); String hash = hashCredentials(keySalt, sha256);
if (hash == null) { if (hash == null) {
return false; return false;
} }
@ -436,7 +440,7 @@ class LxWsSecurityToken extends LxWsSecurity {
try { try {
String hashKey = resp.getValueAsString(); String hashKey = resp.getValueAsString();
// here is a difference to the API spec, which says the string to hash is "user:token", but this is "token" // here is a difference to the API spec, which says the string to hash is "user:token", but this is "token"
String hash = hashString(token, hashKey); String hash = hashString(token, hashKey, sha256);
if (hash == null) { if (hash == null) {
setError(null, "Error hashing token."); setError(null, "Error hashing token.");
} }