com.sap.hana.datalake.files.utils.PemSslUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sap-hdlfs Show documentation
Show all versions of sap-hdlfs Show documentation
An implementation of org.apache.hadoop.fs.FileSystem targeting SAP HANA Data Lake Files.
// © 2022-2023 SAP SE or an SAP affiliate company. All rights reserved.
package com.sap.hana.datalake.files.utils;
import com.sap.hana.datalake.files.HdlfsConstants;
import com.sap.hana.datalake.files.classification.InterfaceAudience;
import com.sap.hana.datalake.files.classification.InterfaceStability;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.PEMDecryptorProvider;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.PEMEncryptedKeyPair;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.PEMKeyPair;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.PEMParser;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.bc.BcPEMDecryptorProvider;
import com.sap.hana.datalake.files.shaded.org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
@InterfaceAudience.Private
@InterfaceStability.Evolving
public final class PemSslUtils {
private static final Pattern PEM_HEADER_PATTERN = Pattern.compile("^-----BEGIN(.+)(CERTIFICATE|PRIVATE KEY)-----(?s).*");
private static final char[] EMPTY_CHAR_ARRAY = new char[0];
private static final String KEY_MANAGER_ALGORITHM = "PKIX";
public static boolean isPemFileContent(final String value) {
return PEM_HEADER_PATTERN.matcher(value).matches();
}
public static KeyManager[] createKeyManagers(final String certificatesValue, final String privateKeyValue) throws IOException, GeneralSecurityException {
return createKeyManagers(certificatesValue, privateKeyValue, /* passphrase */ null);
}
public static KeyManager[] createKeyManagers(final String certificatesValue, final String privateKeyValue, final String passphrase) throws IOException, GeneralSecurityException {
if (certificatesValue == null || certificatesValue.isEmpty() || privateKeyValue == null || privateKeyValue.isEmpty()) {
return null;
}
final List certificateChain = isPemFileContent(certificatesValue) ?
loadCertificateChain(certificatesValue) :
loadCertificateChain(Paths.get(certificatesValue));
final PrivateKey privateKey = isPemFileContent(privateKeyValue) ?
loadPrivateKey(privateKeyValue, passphrase) :
loadPrivateKey(Paths.get(privateKeyValue), passphrase);
return createKeyManagers(certificateChain, privateKey);
}
public static KeyManager[] createKeyManagers(final List certChain, final PrivateKey privateKey) throws GeneralSecurityException, IOException {
if (certChain == null || privateKey == null) {
return null;
}
final KeyStore keyStore = createEmptyJavaKeyStore();
final Certificate[] certChainArray = certChain.toArray(new Certificate[0]);
keyStore.setKeyEntry("client-identity", privateKey, EMPTY_CHAR_ARRAY, certChainArray);
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_ALGORITHM);
keyManagerFactory.init(keyStore, EMPTY_CHAR_ARRAY);
return keyManagerFactory.getKeyManagers();
}
public static TrustManager[] createTrustManagers(final String caCertsValue) throws IOException, GeneralSecurityException {
if (caCertsValue == null || caCertsValue.isEmpty()) {
return null;
}
final List caCerts = isPemFileContent(caCertsValue) ?
loadCertificateChain(caCertsValue) :
loadCertificateChain(Paths.get(caCertsValue));
return createTrustManagers(caCerts);
}
public static TrustManager[] createTrustManagers(final List caCerts) throws IOException, GeneralSecurityException {
if (caCerts == null) {
return null;
}
final KeyStore trustStore = createEmptyJavaKeyStore();
for (int i = 0; i < caCerts.size(); i++) {
trustStore.setCertificateEntry("ca" + i, caCerts.get(i));
}
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KEY_MANAGER_ALGORITHM);
trustManagerFactory.init(trustStore);
return trustManagerFactory.getTrustManagers();
}
private static KeyStore createEmptyJavaKeyStore() throws IOException, GeneralSecurityException {
final KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
return keyStore;
}
private static List loadCertificateChain(final Path certsPath) throws IOException, GeneralSecurityException {
try (final InputStream is = Files.newInputStream(certsPath)) {
return loadCertificateChain(is);
}
}
private static List loadCertificateChain(final String certsData) throws IOException, GeneralSecurityException {
try (final InputStream is = new ByteArrayInputStream(certsData.getBytes(HdlfsConstants.DEFAULT_CHARSET))) {
return loadCertificateChain(is);
}
}
private static List loadCertificateChain(final InputStream certsDataInputStream) throws IOException, GeneralSecurityException {
final CertificateFactory factory = new CertificateFactory();
final List certificates = new ArrayList<>();
try (final BufferedInputStream bis = new BufferedInputStream(certsDataInputStream)) {
while (bis.available() > 0) {
final Certificate cert = factory.engineGenerateCertificate(bis);
certificates.add(cert);
}
return certificates;
}
}
private static PrivateKey loadPrivateKey(final Path privateKeyPath, final String passphrase) throws IOException {
try (final InputStream privateKeyIn = Files.newInputStream(privateKeyPath);
final Reader privateKeyReader = new InputStreamReader(privateKeyIn)) {
return loadPrivateKey(privateKeyReader, passphrase);
}
}
private static PrivateKey loadPrivateKey(final String privateKeyData, final String passphrase) throws IOException {
try (final Reader privateKeyReader = new StringReader(privateKeyData)) {
return loadPrivateKey(privateKeyReader, passphrase);
}
}
private static PrivateKey loadPrivateKey(final Reader privateKeyReader, final String passphrase) throws IOException {
final PEMParser pemParser = new PEMParser(privateKeyReader);
final Object parsedObject = pemParser.readObject();
final PrivateKeyInfo privateKeyInfo;
if (parsedObject instanceof PrivateKeyInfo) {
privateKeyInfo = (PrivateKeyInfo) parsedObject;
} else if (parsedObject instanceof PEMKeyPair) {
privateKeyInfo = ((PEMKeyPair) parsedObject).getPrivateKeyInfo();
} else if (parsedObject instanceof PEMEncryptedKeyPair) {
final char[] passphraseChars = Optional.ofNullable(passphrase).orElse(HdlfsConstants.FS_HDLFS_SSL_KEYFILE_PASSWORD_DEFAULT).toCharArray();
final PEMDecryptorProvider decryptorProvider = new BcPEMDecryptorProvider(passphraseChars);
final PEMKeyPair pemKeyPair = ((PEMEncryptedKeyPair) parsedObject).decryptKeyPair(decryptorProvider);
privateKeyInfo = pemKeyPair.getPrivateKeyInfo();
} else {
throw new IOException(String.format("Unsupported PrivateKey; parsed object class [%s]", parsedObject.getClass().getName()));
}
return privateKeyInfo == null ? null : new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
}
}
// © 2022-2023 SAP SE or an SAP affiliate company. All rights reserved.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy