using random salt within the encrypted cipher now

This commit is contained in:
anhefti 2019-04-17 11:17:12 +02:00
parent 34a1f14eb0
commit 915a7674fd
3 changed files with 45 additions and 74 deletions

View file

@ -12,53 +12,28 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
public interface ClientCredentialService { public interface ClientCredentialService {
Result<ClientCredentials> createGeneratedClientCredentials(CharSequence salt); Result<ClientCredentials> createGeneratedClientCredentials();
default Result<ClientCredentials> createGeneratedClientCredentials() {
return createGeneratedClientCredentials(null);
}
ClientCredentials encryptClientCredentials( ClientCredentials encryptClientCredentials(
CharSequence clientIdPlaintext, CharSequence clientIdPlaintext,
CharSequence secretPlaintext, CharSequence secretPlaintext,
CharSequence accessTokenPlaintext, CharSequence accessTokenPlaintext);
CharSequence salt);
default ClientCredentials encryptClientCredentials( default ClientCredentials encryptClientCredentials(
final CharSequence clientIdPlaintext, final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext) { final CharSequence secretPlaintext) {
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, null, null); return encryptClientCredentials(clientIdPlaintext, secretPlaintext, null);
} }
default ClientCredentials encryptClientCredentials( CharSequence getPlainClientId(ClientCredentials credentials);
final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext,
final CharSequence accessTokenPlaintext) {
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, accessTokenPlaintext, null); CharSequence getPlainClientSecret(ClientCredentials credentials);
}
CharSequence getPlainClientId(ClientCredentials credentials, CharSequence salt); CharSequence getPlainAccessToken(ClientCredentials credentials);
default CharSequence getPlainClientId(final ClientCredentials credentials) {
return getPlainClientId(credentials, null);
}
CharSequence getPlainClientSecret(ClientCredentials credentials, CharSequence salt);
default CharSequence getPlainClientSecret(final ClientCredentials credentials) {
return getPlainClientSecret(credentials, null);
}
CharSequence getPlainAccessToken(ClientCredentials credentials, CharSequence salt);
default CharSequence getPlainAccessToken(final ClientCredentials credentials) {
return getPlainAccessToken(credentials, null);
}
CharSequence encrypt(final CharSequence text); CharSequence encrypt(final CharSequence text);
CharSequence decrypt(final CharSequence text); CharSequence decrypt(final CharSequence cipher);
} }

View file

@ -9,7 +9,6 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.client; package ch.ethz.seb.sebserver.webservice.servicelayer.client;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.CharBuffer;
import java.security.SecureRandom; import java.security.SecureRandom;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
@ -19,8 +18,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.crypto.encrypt.Encryptors; import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -34,9 +33,6 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
private static final Logger log = LoggerFactory.getLogger(ClientCredentialServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(ClientCredentialServiceImpl.class);
static final String SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY = "sebserver.webservice.internalSecret"; static final String SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY = "sebserver.webservice.internalSecret";
static final CharSequence DEFAULT_SALT =
CharBuffer.wrap(
new char[] { 'b', '7', 'd', 'b', 'e', '9', '9', 'b', 'b', 'f', 'a', '3', 'e', '2', '1', 'e' });
private final Environment environment; private final Environment environment;
@ -48,14 +44,13 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
} }
@Override @Override
public Result<ClientCredentials> createGeneratedClientCredentials(final CharSequence salt) { public Result<ClientCredentials> createGeneratedClientCredentials() {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
try { try {
return encryptClientCredentials( return encryptClientCredentials(
generateClientId(), generateClientId(),
generateClientSecret(), generateClientSecret());
salt);
} catch (final UnsupportedEncodingException e) { } catch (final UnsupportedEncodingException e) {
log.error("Error while trying to generate client credentials: ", e); log.error("Error while trying to generate client credentials: ", e);
@ -68,26 +63,25 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
public ClientCredentials encryptClientCredentials( public ClientCredentials encryptClientCredentials(
final CharSequence clientIdPlaintext, final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext, final CharSequence secretPlaintext,
final CharSequence accessTokenPlaintext, final CharSequence accessTokenPlaintext) {
final CharSequence salt) {
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return new ClientCredentials( return new ClientCredentials(
(clientIdPlaintext != null) (clientIdPlaintext != null)
? encrypt(clientIdPlaintext, secret, salt).toString() ? encrypt(clientIdPlaintext, secret).toString()
: null, : null,
(secretPlaintext != null) (secretPlaintext != null)
? encrypt(secretPlaintext, secret, salt).toString() ? encrypt(secretPlaintext, secret).toString()
: null, : null,
(accessTokenPlaintext != null) (accessTokenPlaintext != null)
? encrypt(accessTokenPlaintext, secret, salt).toString() ? encrypt(accessTokenPlaintext, secret).toString()
: null); : null);
} }
@Override @Override
public CharSequence getPlainClientId(final ClientCredentials credentials, final CharSequence salt) { public CharSequence getPlainClientId(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasClientId()) { if (credentials == null || !credentials.hasClientId()) {
return null; return null;
} }
@ -95,76 +89,85 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.clientId, secret, salt); return this.decrypt(credentials.clientId, secret);
} }
@Override @Override
public CharSequence getPlainClientSecret(final ClientCredentials credentials, final CharSequence salt) { public CharSequence getPlainClientSecret(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasSecret()) { if (credentials == null || !credentials.hasSecret()) {
return null; return null;
} }
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.secret, secret, salt); return this.decrypt(credentials.secret, secret);
} }
@Override @Override
public CharSequence getPlainAccessToken(final ClientCredentials credentials, final CharSequence salt) { public CharSequence getPlainAccessToken(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasAccessToken()) { if (credentials == null || !credentials.hasAccessToken()) {
return null; return null;
} }
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.accessToken, secret, salt); return this.decrypt(credentials.accessToken, secret);
} }
@Override @Override
public CharSequence encrypt(final CharSequence text) { public CharSequence encrypt(final CharSequence text) {
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return encrypt(text, secret, null); return encrypt(text, secret);
} }
@Override @Override
public CharSequence decrypt(final CharSequence text) { public CharSequence decrypt(final CharSequence text) {
final CharSequence secret = this.environment final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY); .getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return decrypt(text, secret, null); return decrypt(text, secret);
} }
CharSequence encrypt(final CharSequence text, final CharSequence secret, final CharSequence salt) { CharSequence encrypt(final CharSequence text, final CharSequence secret) {
if (text == null) { if (text == null) {
throw new IllegalArgumentException("Text has null reference"); throw new IllegalArgumentException("Text has null reference");
} }
try { try {
return Encryptors final CharSequence salt = KeyGenerators.string().generateKey();
.delux(secret, getSalt(salt)) final CharSequence cipher = Encryptors
.delux(secret, salt)
.encrypt(text.toString()); .encrypt(text.toString());
return new StringBuilder(cipher)
.append(salt);
} catch (final Exception e) { } catch (final Exception e) {
log.error("Failed to encrypt text: ", e); log.error("Failed to encrypt text: ", e);
return text; throw e;
} }
} }
CharSequence decrypt(final CharSequence text, final CharSequence secret, final CharSequence salt) { CharSequence decrypt(final CharSequence cipher, final CharSequence secret) {
if (text == null) { if (cipher == null) {
throw new IllegalArgumentException("Text has null reference"); throw new IllegalArgumentException("Cipher has null reference");
} }
try { try {
final int length = cipher.length();
final int cipherTextLength = length - 16;
final CharSequence salt = cipher.subSequence(cipherTextLength, length);
final CharSequence cipherText = cipher.subSequence(0, cipherTextLength);
return Encryptors return Encryptors
.delux(secret, getSalt(salt)) .delux(secret, salt)
.decrypt(text.toString()); .decrypt(cipherText.toString());
} catch (final Exception e) { } catch (final Exception e) {
log.error("Failed to decrypt text: ", e); log.error("Failed to decrypt text: ", e);
return text; throw e;
} }
} }
@ -172,13 +175,6 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?")) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?"))
.toCharArray(); .toCharArray();
private CharSequence getSalt(final CharSequence saltPlain) throws UnsupportedEncodingException {
final CharSequence _salt = (saltPlain == null || saltPlain.length() <= 0)
? this.environment.getProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY, DEFAULT_SALT.toString())
: saltPlain;
return new String(Hex.encode(_salt.toString().getBytes("UTF-8")));
}
private CharSequence generateClientId() { private CharSequence generateClientId() {
return RandomStringUtils.random( return RandomStringUtils.random(
16, 0, possibleCharacters.length - 1, false, false, 16, 0, possibleCharacters.length - 1, false, false,

View file

@ -39,16 +39,16 @@ public class ClientCredentialServiceTest {
final ClientCredentialServiceImpl service = new ClientCredentialServiceImpl(envMock); final ClientCredentialServiceImpl service = new ClientCredentialServiceImpl(envMock);
String encrypted = String encrypted =
service.encrypt(clientName, "secret1", ClientCredentialServiceImpl.DEFAULT_SALT).toString(); service.encrypt(clientName, "secret1").toString();
String decrypted = service.decrypt(encrypted, "secret1", ClientCredentialServiceImpl.DEFAULT_SALT).toString(); String decrypted = service.decrypt(encrypted, "secret1").toString();
assertEquals(clientName, decrypted); assertEquals(clientName, decrypted);
final String clientSecret = "fbjreij39ru29305ruࣣàèLöäöäü65%(/%(ç87"; final String clientSecret = "fbjreij39ru29305ruࣣàèLöäöäü65%(/%(ç87";
encrypted = encrypted =
service.encrypt(clientSecret, "secret1", ClientCredentialServiceImpl.DEFAULT_SALT).toString(); service.encrypt(clientSecret, "secret1").toString();
decrypted = service.decrypt(encrypted, "secret1", ClientCredentialServiceImpl.DEFAULT_SALT).toString(); decrypted = service.decrypt(encrypted, "secret1").toString();
assertEquals(clientSecret, decrypted); assertEquals(clientSecret, decrypted);
} }