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 {
Result<ClientCredentials> createGeneratedClientCredentials(CharSequence salt);
default Result<ClientCredentials> createGeneratedClientCredentials() {
return createGeneratedClientCredentials(null);
}
Result<ClientCredentials> createGeneratedClientCredentials();
ClientCredentials encryptClientCredentials(
CharSequence clientIdPlaintext,
CharSequence secretPlaintext,
CharSequence accessTokenPlaintext,
CharSequence salt);
CharSequence accessTokenPlaintext);
default ClientCredentials encryptClientCredentials(
final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext) {
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, null, null);
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, null);
}
default ClientCredentials encryptClientCredentials(
final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext,
final CharSequence accessTokenPlaintext) {
CharSequence getPlainClientId(ClientCredentials credentials);
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, accessTokenPlaintext, null);
}
CharSequence getPlainClientSecret(ClientCredentials credentials);
CharSequence getPlainClientId(ClientCredentials credentials, CharSequence salt);
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 getPlainAccessToken(ClientCredentials credentials);
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;
import java.io.UnsupportedEncodingException;
import java.nio.CharBuffer;
import java.security.SecureRandom;
import org.apache.commons.lang3.RandomStringUtils;
@ -19,8 +18,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
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.keygen.KeyGenerators;
import org.springframework.stereotype.Service;
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);
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;
@ -48,14 +44,13 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
}
@Override
public Result<ClientCredentials> createGeneratedClientCredentials(final CharSequence salt) {
public Result<ClientCredentials> createGeneratedClientCredentials() {
return Result.tryCatch(() -> {
try {
return encryptClientCredentials(
generateClientId(),
generateClientSecret(),
salt);
generateClientSecret());
} catch (final UnsupportedEncodingException e) {
log.error("Error while trying to generate client credentials: ", e);
@ -68,26 +63,25 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
public ClientCredentials encryptClientCredentials(
final CharSequence clientIdPlaintext,
final CharSequence secretPlaintext,
final CharSequence accessTokenPlaintext,
final CharSequence salt) {
final CharSequence accessTokenPlaintext) {
final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return new ClientCredentials(
(clientIdPlaintext != null)
? encrypt(clientIdPlaintext, secret, salt).toString()
? encrypt(clientIdPlaintext, secret).toString()
: null,
(secretPlaintext != null)
? encrypt(secretPlaintext, secret, salt).toString()
? encrypt(secretPlaintext, secret).toString()
: null,
(accessTokenPlaintext != null)
? encrypt(accessTokenPlaintext, secret, salt).toString()
? encrypt(accessTokenPlaintext, secret).toString()
: null);
}
@Override
public CharSequence getPlainClientId(final ClientCredentials credentials, final CharSequence salt) {
public CharSequence getPlainClientId(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasClientId()) {
return null;
}
@ -95,76 +89,85 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.clientId, secret, salt);
return this.decrypt(credentials.clientId, secret);
}
@Override
public CharSequence getPlainClientSecret(final ClientCredentials credentials, final CharSequence salt) {
public CharSequence getPlainClientSecret(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasSecret()) {
return null;
}
final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.secret, secret, salt);
return this.decrypt(credentials.secret, secret);
}
@Override
public CharSequence getPlainAccessToken(final ClientCredentials credentials, final CharSequence salt) {
public CharSequence getPlainAccessToken(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasAccessToken()) {
return null;
}
final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return this.decrypt(credentials.accessToken, secret, salt);
return this.decrypt(credentials.accessToken, secret);
}
@Override
public CharSequence encrypt(final CharSequence text) {
final CharSequence secret = this.environment
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
return encrypt(text, secret, null);
return encrypt(text, secret);
}
@Override
public CharSequence decrypt(final CharSequence text) {
final CharSequence secret = this.environment
.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) {
throw new IllegalArgumentException("Text has null reference");
}
try {
return Encryptors
.delux(secret, getSalt(salt))
final CharSequence salt = KeyGenerators.string().generateKey();
final CharSequence cipher = Encryptors
.delux(secret, salt)
.encrypt(text.toString());
return new StringBuilder(cipher)
.append(salt);
} catch (final Exception e) {
log.error("Failed to encrypt text: ", e);
return text;
throw e;
}
}
CharSequence decrypt(final CharSequence text, final CharSequence secret, final CharSequence salt) {
if (text == null) {
throw new IllegalArgumentException("Text has null reference");
CharSequence decrypt(final CharSequence cipher, final CharSequence secret) {
if (cipher == null) {
throw new IllegalArgumentException("Cipher has null reference");
}
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
.delux(secret, getSalt(salt))
.decrypt(text.toString());
.delux(secret, salt)
.decrypt(cipherText.toString());
} catch (final Exception e) {
log.error("Failed to decrypt text: ", e);
return text;
throw e;
}
}
@ -172,13 +175,6 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?"))
.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() {
return RandomStringUtils.random(
16, 0, possibleCharacters.length - 1, false, false,

View file

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