using random salt within the encrypted cipher now
This commit is contained in:
parent
34a1f14eb0
commit
915a7674fd
3 changed files with 45 additions and 74 deletions
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue