Skip to content

Commit

Permalink
fix of private key format(MID-7034)
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Jul 8, 2021
1 parent 3c133e6 commit b8a3b34
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 13 deletions.
4 changes: 4 additions & 0 deletions gui/admin-gui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ protected ServiceProviderService getHostedServiceProvider(LocalServiceProviderCo
SimpleKey activeKey = spConfig.getKeys().getActive();
if (activeKey != null) {
keys.add(activeKey);
keys.add(activeKey.clone(activeKey.getName() + "-encryption", KeyType.ENCRYPTION));
keys.add(activeKey.clone(activeKey.getName(), KeyType.ENCRYPTION));
}
keys.addAll(spConfig.getKeys().getStandBy());
signingKey = spConfig.isSignMetadata() ? spConfig.getKeys().getActive() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,30 @@
package com.evolveum.midpoint.web.security;

import com.evolveum.midpoint.web.security.util.KeyStoreKey;

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.springframework.security.saml.SamlKeyException;
import org.springframework.security.saml.key.SimpleKey;
import org.springframework.security.saml.spi.SamlKeyStoreProvider;
import org.springframework.security.saml.util.X509Utilities;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;

import static java.util.Optional.ofNullable;
import static org.springframework.util.StringUtils.hasText;

/**
Expand Down Expand Up @@ -53,7 +60,71 @@ public KeyStore getKeyStore(SimpleKey key) {
throw new SamlKeyException(e);
}
} else {
return SamlKeyStoreProvider.super.getKeyStore(key);
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, DEFAULT_KS_PASSWD);

byte[] certbytes = X509Utilities.getDER(key.getCertificate());
Certificate certificate = X509Utilities.getCertificate(certbytes);
ks.setCertificateEntry(key.getName(), certificate);

if (hasText(key.getPrivateKey())) {
PrivateKey pkey;
Object obj = null;
try {
PEMParser parser = new PEMParser(new CharArrayReader(key.getPrivateKey().toCharArray()));
obj = parser.readObject();
parser.close();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
if (obj == null) {
throw new SamlKeyException("Unable to decode PEM key:" + key.getPrivateKey());
}
else if (obj instanceof PEMEncryptedKeyPair) {

// Encrypted key - we will use provided password
PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) obj;
char[] passarray = (ofNullable(key.getPassphrase()).orElse("")).toCharArray();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passarray);
KeyPair kp = converter.getKeyPair(ckp.decryptKeyPair(decProv));
pkey = kp.getPrivate();
}
else if (obj instanceof PEMKeyPair) {
// Unencrypted key - no password needed
PEMKeyPair ukp = (PEMKeyPair) obj;
KeyPair kp = converter.getKeyPair(ukp);
pkey = kp.getPrivate();
}
else if (obj instanceof PrivateKeyInfo) {
// Encrypted key - we will use provided password
PrivateKeyInfo pk = (PrivateKeyInfo) obj;
pkey = converter.getPrivateKey(pk);
}
else if (obj instanceof PKCS8EncryptedPrivateKeyInfo) {
// Encrypted key - we will use provided password
PKCS8EncryptedPrivateKeyInfo cpk = (PKCS8EncryptedPrivateKeyInfo) obj;
char[] passarray = (ofNullable(key.getPassphrase()).orElse("")).toCharArray();
final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passarray);
pkey = converter.getPrivateKey(cpk.decryptPrivateKeyInfo(provider));
}
else {
throw new SamlKeyException("Unable get private key from " + obj);
}
} catch (IOException e) {
throw new SamlKeyException("Unable get private key", e);
} catch (OperatorCreationException | PKCSException e) {
throw new SamlKeyException("Unable get private key from " + obj, e);
}

ks.setKeyEntry(key.getName(), pkey, key.getPassphrase().toCharArray(), new
Certificate[]{certificate});
}

return ks;
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
throw new SamlKeyException(e);
} catch (IOException e) {
throw new SamlKeyException(e);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,10 @@ private static KeyStoreKey createKeyStoreKey(ModuleSaml2KeyStoreKeyType keyStore
KeyStoreKey key = new KeyStoreKey();
key.setKeyAlias(keyStoreKeyType.getKeyAlias());
// Protector protector = ((MidPointApplication) Application.get()).getProtector();
String keyPassword = protector.decryptString(keyStoreKeyType.getKeyPassword());
key.setKeyPassword(keyPassword);
if (keyStoreKeyType.getKeyPassword() != null) {
String keyPassword = protector.decryptString(keyStoreKeyType.getKeyPassword());
key.setKeyPassword(keyPassword);
}
String keyStorePath = keyStoreKeyType.getKeyStorePath();
key.setKeyStorePath(keyStorePath);
String keyStorePassword = protector.decryptString(keyStoreKeyType.getKeyStorePassword());
Expand Down
15 changes: 14 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
<selenium.version>3.141.59</selenium.version>
<slf4j.version>1.7.30</slf4j.version>
<logback.version>1.2.3e1</logback.version>
<spring.security.saml2.version>2.0.0.M30</spring.security.saml2.version>
<spring.security.saml2.version>2.0.0.M31</spring.security.saml2.version>
<cache2k.version>2.0.0.Final</cache2k.version>
<testng.version>7.4.0</testng.version>
<xml.resolver.version>1.2</xml.resolver.version>
Expand Down Expand Up @@ -1013,8 +1013,21 @@
<groupId>org.opensaml</groupId>
<artifactId>opensaml-core</artifactId>
</exclusion>
<exclusion>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.activation</groupId>
<artifactId>:javax.activation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.69</version>
</dependency>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-api</artifactId>
Expand Down

0 comments on commit b8a3b34

Please sign in to comment.