package at.asitplus.eidas.specific.modules.auth.eidas.v2.service; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Provider; import java.security.cert.X509Certificate; import java.util.Base64; import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.jose4j.lang.JoseException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; import at.gv.egiz.eaaf.core.impl.data.Pair; import lombok.extern.slf4j.Slf4j; /** * Service to build and sign AuthBlock's for E-ID system. * * @author tlenz * */ @Slf4j @Service("authBlockSigningService") public class AuthBlockSigningService { private static final String KEYSTORE_FRIENDLYNAME = "AuthBlock_Signing"; private static ObjectMapper mapper = new ObjectMapper(); @Autowired IConfiguration basicConfig; @Autowired EaafKeyStoreFactory keyStoreFactory; private Pair keyStore; /** * Build and sign an AuthBlock for E-ID system. * * @param dataToSign data that should be added into AuthBlock * @return serialized JWS * @throws JsonProcessingException In case of a AuthBlock generation error * @throws JoseException In case of a JWS signing error * @throws EaafException In case of a KeyStore or Key error */ public String buildSignedAuthBlock(String dataToSign) throws JsonProcessingException, EaafException, JoseException { log.debug("Building and sign authBlock with data: {}", dataToSign); // build AuthBlock String jwsPayload = mapper.writeValueAsString(dataToSign); //sign JWS return JoseUtils .createSignature(keyStore, getKeyAlias(), getKeyPassword(), jwsPayload, false, KEYSTORE_FRIENDLYNAME); } /** * Get the Base64 encoded PublicKey that is used to sign the AuthBlock. * * @return Base64 encoded PublicKey * @throws EaafKeyAccessException In case of an unknown or invalid key */ public String getBase64EncodedPublicKey() throws EaafKeyAccessException { Pair keyPair = EaafKeyStoreUtils.getPrivateKeyAndCertificates( keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME); return Base64.getEncoder().encodeToString(keyPair.getSecond()[0].getPublicKey().getEncoded()); } @PostConstruct private void initialize() throws KeyStoreException, EaafException { log.debug("Initializing AuthBlock signing service ... "); // read Connector wide config data TODO connector wide! String keyStoreName = basicConfig .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME); String keyStorePw = basicConfig .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD); String keyStorePath = basicConfig .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH); String keyStoreType = basicConfig .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE); //build new KeyStore configuration KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration(); keyStoreConfiguration.setFriendlyName(KEYSTORE_FRIENDLYNAME); keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath); keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw); keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType)); keyStoreConfiguration.setKeyStoreName(keyStoreName); //validate KeyStore configuration keyStoreConfiguration.validate(); //validate key alias if (StringUtils.isEmpty(getKeyAlias())) { throw new EaafConfigurationException("config.08", new Object[] {MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS}); } //build new KeyStore based on configuration keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfiguration); log.info("AuthBlock signing-service successful initialized"); } private char[] getKeyPassword() { final String value = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD); if (value != null) { return value.trim().toCharArray(); } return null; } private String getKeyAlias() { return basicConfig .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS); } }