Merge pull request #873 from stianst/master

Use HmacSHA256 for code signatures
This commit is contained in:
Stian Thorgersen 2014-11-27 10:34:51 +01:00
commit 5c2e7df7de
8 changed files with 49 additions and 14 deletions

View file

@ -2,6 +2,7 @@ package org.keycloak.models;
import org.keycloak.enums.SslRequired;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
@ -99,6 +100,8 @@ public interface RealmModel extends RoleContainerModel {
String getCodeSecret();
Key getCodeSecretKey();
void setCodeSecret(String codeSecret);
X509Certificate getCertificate();

View file

@ -15,6 +15,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.util.CertificateUtils;
import org.keycloak.util.PemUtils;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.StringWriter;
import java.security.Key;
@ -77,6 +78,10 @@ public final class KeycloakModelUtils {
return null;
}
public static Key getSecretKey(String secret) {
return secret != null ? new SecretKeySpec(secret.getBytes(), "HmacSHA256") : null;
}
public static String getPemFromKey(Key key) {
StringWriter writer = new StringWriter();
PEMWriter pemWriter = new PEMWriter(writer);

View file

@ -13,6 +13,7 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.cache.entities.CachedRealm;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
@ -34,6 +35,7 @@ public class RealmAdapter implements RealmModel {
protected RealmCache cache;
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
protected volatile transient Key codeSecretKey;
protected volatile transient X509Certificate certificate;
public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
@ -379,6 +381,14 @@ public class RealmAdapter implements RealmModel {
return updated != null ? updated.getCodeSecret() : cached.getCodeSecret();
}
@Override
public Key getCodeSecretKey() {
if (codeSecretKey == null) {
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
}
return codeSecretKey;
}
@Override
public void setCodeSecret(String codeSecret) {
getDelegateForUpdate();

View file

@ -21,6 +21,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
@ -46,6 +47,7 @@ public class RealmAdapter implements RealmModel {
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
protected volatile transient X509Certificate certificate;
protected volatile transient Key codeSecretKey;
protected KeycloakSession session;
private PasswordPolicy passwordPolicy;
@ -439,6 +441,14 @@ public class RealmAdapter implements RealmModel {
return realm.getCodeSecret();
}
@Override
public Key getCodeSecretKey() {
if (codeSecretKey == null) {
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
}
return codeSecretKey;
}
@Override
public void setCodeSecret(String codeSecret) {
realm.setCodeSecret(codeSecret);

View file

@ -23,6 +23,7 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
@ -43,14 +44,13 @@ import java.util.Set;
*/
public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> implements RealmModel {
private static final Logger logger = Logger.getLogger(RealmAdapter.class);
private final MongoRealmEntity realm;
private final RealmProvider model;
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
protected volatile transient X509Certificate certificate;
protected volatile transient Key codeSecretKey;
private volatile transient PasswordPolicy passwordPolicy;
private volatile transient KeycloakSession session;
@ -424,6 +424,14 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
return realm.getCodeSecret();
}
@Override
public Key getCodeSecretKey() {
if (codeSecretKey == null) {
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
}
return codeSecretKey;
}
@Override
public void setCodeSecret(String codeSecret) {
realm.setCodeSecret(codeSecret);

View file

@ -108,7 +108,7 @@
<module>events</module>
<module>model</module>
<module>integration</module>
<module>proxy/proxy-server</module>
<module>proxy</module>
<module>picketlink</module>
<module>federation</module>
<module>services</module>

View file

@ -8,7 +8,8 @@ import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.util.Base64Url;
import org.keycloak.util.Time;
import java.security.MessageDigest;
import javax.crypto.Mac;
import java.security.Key;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@ -147,13 +148,13 @@ public class ClientSessionCode {
private static String createHash(RealmModel realm, ClientSessionModel clientSession) {
try {
MessageDigest digest = MessageDigest.getInstance("sha-256");
digest.update(realm.getCodeSecret().getBytes());
digest.update(HASH_SEPERATOR);
digest.update(clientSession.getId().getBytes());
digest.update(HASH_SEPERATOR);
digest.update(clientSession.getNote(ACTION_KEY).getBytes());
return Base64Url.encode(digest.digest());
Key codeSecretKey = realm.getCodeSecretKey();
Mac mac = Mac.getInstance(codeSecretKey.getAlgorithm());
mac.init(codeSecretKey);
mac.update(clientSession.getId().getBytes());
mac.update(HASH_SEPERATOR);
mac.update(clientSession.getNote(ACTION_KEY).getBytes());
return Base64Url.encode(mac.doFinal());
} catch (Exception e) {
throw new RuntimeException(e);
}

View file

@ -73,9 +73,7 @@ import java.security.Principal;
import java.util.Enumeration;
import java.util.regex.Matcher;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Ignore
public class ProxyTest {
static String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
.queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString();