/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.component.crypto; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.cert.Certificate; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriParams; import org.apache.camel.spi.UriPath; import org.apache.camel.util.jsse.KeyStoreParameters; @UriParams public class DigitalSignatureConfiguration implements Cloneable, CamelContextAware { private CamelContext context; @UriPath @Metadata(required = "true") private CryptoOperation cryptoOperation; @UriPath @Metadata(required = "true") private String name; @UriParam(secret = true) private PrivateKey privateKey; @UriParam(label = "advanced") private KeyStoreParameters keyStoreParameters; @UriParam private KeyStore keystore; @UriParam(label = "advanced", secret = true) private SecureRandom secureRandom; @UriParam(defaultValue = "SHA1WithDSA") private String algorithm = "SHA1WithDSA"; @UriParam(label = "advanced", defaultValue = "" + 2048) private Integer bufferSize = 2048; @UriParam private String provider; @UriParam private String signatureHeaderName; @UriParam private String alias; @UriParam(label = "security", javaType = "java.lang.String", secret = true) private char[] password; @UriParam(label = "advanced") private PublicKey publicKey; @UriParam(label = "advanced") private Certificate certificate; /** references that should be resolved when the context changes */ @UriParam private String publicKeyName; @UriParam private String certificateName; @UriParam(secret = true) private String privateKeyName; @UriParam private String keystoreName; @UriParam private String secureRandomName; @UriParam(label = "advanced", defaultValue = "true") private boolean clearHeaders = true; public DigitalSignatureConfiguration copy() { try { return (DigitalSignatureConfiguration)clone(); } catch (CloneNotSupportedException e) { throw new RuntimeCamelException(e); } } public CamelContext getCamelContext() { return context; } public void setCamelContext(CamelContext camelContext) { // TODO: this is wrong a configuration should not have CamelContext this.context = camelContext; // try to retrieve the references once the context is available. setKeystoreName(keystoreName); setPublicKeyName(publicKeyName); setPrivateKeyName(privateKeyName); setCertificateName(certificateName); setSecureRandomName(secureRandomName); } public String getName() { return name; } /** * The logical name of this operation. */ public void setName(String name) { this.name = name; } /** * Gets the JCE name of the Algorithm that should be used for the signer. */ public String getAlgorithm() { return algorithm; } /** * Sets the JCE name of the Algorithm that should be used for the signer. */ public void setAlgorithm(String algorithm) { this.algorithm = algorithm; } /** * Gets the alias used to query the KeyStore for keys and {@link java.security.cert.Certificate Certificates} * to be used in signing and verifying exchanges. This value can be provided at runtime via the message header * {@link org.apache.camel.component.crypto.DigitalSignatureConstants#KEYSTORE_ALIAS} */ public String getAlias() { return alias; } /** * Sets the alias used to query the KeyStore for keys and {@link java.security.cert.Certificate Certificates} * to be used in signing and verifying exchanges. This value can be provided at runtime via the message header * {@link org.apache.camel.component.crypto.DigitalSignatureConstants#KEYSTORE_ALIAS} */ public void setAlias(String alias) { this.alias = alias; } /** * Get the PrivateKey that should be used to sign the exchange */ public PrivateKey getPrivateKey() throws Exception { return getPrivateKey(alias, password); } /** * Get the PrivateKey that should be used to sign the signature in the * exchange using the supplied alias. * * @param alias the alias used to retrieve the Certificate from the keystore. */ public PrivateKey getPrivateKey(String alias) throws Exception { return getPrivateKey(alias, password); } /** * Get the PrivateKey that should be used to sign the signature in the * exchange using the supplied alias. * * @param alias the alias used to retrieve the Certificate from the keystore. */ public PrivateKey getPrivateKey(String alias, char[] password) throws Exception { PrivateKey pk = null; if (alias != null && keystore != null) { pk = (PrivateKey)keystore.getKey(alias, password); } if (pk == null) { pk = privateKey; } return pk; } /** * Set the PrivateKey that should be used to sign the exchange * * @param privateKey the key with with to sign the exchange. */ public void setPrivateKey(PrivateKey privateKey) { this.privateKey = privateKey; } /** * Sets the reference name for a PrivateKey that can be fond in the registry. */ public void setPrivateKeyName(String privateKeyName) { if (context != null && privateKeyName != null) { PrivateKey pk = context.getRegistry().lookupByNameAndType(privateKeyName, PrivateKey.class); if (pk != null) { setPrivateKey(pk); } } if (privateKeyName != null) { this.privateKeyName = privateKeyName; } } /** * Set the PublicKey that should be used to verify the signature in the exchange. */ public void setPublicKey(PublicKey publicKey) { this.publicKey = publicKey; } /** * Sets the reference name for a publicKey that can be fond in the registry. */ public void setPublicKeyName(String publicKeyName) { if (context != null && publicKeyName != null) { PublicKey pk = context.getRegistry().lookupByNameAndType(publicKeyName, PublicKey.class); if (pk != null) { setPublicKey(pk); } } if (publicKeyName != null) { this.publicKeyName = publicKeyName; } } /** * get the PublicKey that should be used to verify the signature in the exchange. */ public PublicKey getPublicKey() { return publicKey; } /** * Set the Certificate that should be used to verify the signature in the * exchange. If a {@link KeyStore} has been configured then this will * attempt to retrieve the {@link Certificate}from it using hte supplied * alias. If either the alias or the Keystore is invalid then the configured * certificate will be returned * * @param alias the alias used to retrieve the Certificate from the keystore. */ public Certificate getCertificate(String alias) throws Exception { Certificate cert = null; if (alias != null && keystore != null) { cert = keystore.getCertificate(alias); } if (cert == null) { cert = certificate; } return cert; } /** * Get the explicitly configured {@link Certificate} that should be used to * verify the signature in the exchange. */ public Certificate getCertificate() throws Exception { return certificate; } /** * Set the Certificate that should be used to verify the signature in the * exchange based on its payload. */ public void setCertificate(Certificate certificate) { this.certificate = certificate; } /** * Sets the reference name for a PrivateKey that can be fond in the registry. */ public void setCertificateName(String certificateName) { if (context != null && certificateName != null) { Certificate certificate = context.getRegistry().lookupByNameAndType(certificateName, Certificate.class); if (certificate != null) { setCertificate(certificate); } } if (certificateName != null) { this.certificateName = certificateName; } } /** * Gets the KeyStore that can contain keys and Certficates for use in * signing and verifying exchanges. A {@link KeyStore} is typically used * with an alias, either one supplied in the Route definition or dynamically * via the message header "CamelSignatureKeyStoreAlias". If no alias is * supplied and there is only a single entry in the Keystore, then this * single entry will be used. */ public KeyStore getKeystore() { return keystore; } /** * Sets the KeyStore that can contain keys and Certficates for use in * signing and verifying exchanges. A {@link KeyStore} is typically used * with an alias, either one supplied in the Route definition or dynamically * via the message header "CamelSignatureKeyStoreAlias". If no alias is * supplied and there is only a single entry in the Keystore, then this * single entry will be used. */ public void setKeystore(KeyStore keystore) { this.keystore = keystore; } /** * Sets the reference name for a Keystore that can be fond in the registry. */ public void setKeystoreName(String keystoreName) { if (context != null && keystoreName != null) { KeyStore keystore = context.getRegistry().lookupByNameAndType(keystoreName, KeyStore.class); if (keystore != null) { setKeystore(keystore); } } if (keystoreName != null) { this.keystoreName = keystoreName; } } /** * Gets the password used to access an aliased {@link PrivateKey} in the KeyStore. */ public char[] getPassword() { return password; } /** * Sets the password used to access an aliased {@link PrivateKey} in the KeyStore. */ public void setPassword(char[] password) { this.password = password; } public KeyStoreParameters getKeyStoreParameters() { return keyStoreParameters; } /** * Sets the KeyStore that can contain keys and Certficates for use in * signing and verifying exchanges based on the given KeyStoreParameters. * A {@link KeyStore} is typically used * with an alias, either one supplied in the Route definition or dynamically * via the message header "CamelSignatureKeyStoreAlias". If no alias is * supplied and there is only a single entry in the Keystore, then this * single entry will be used. */ public void setKeyStoreParameters(KeyStoreParameters keyStoreParameters) throws Exception { this.keyStoreParameters = keyStoreParameters; if (keyStoreParameters != null) { this.keystore = keyStoreParameters.createKeyStore(); } } /** * Get the SecureRandom used to initialize the Signature service */ public SecureRandom getSecureRandom() { return secureRandom; } /** * Sets the reference name for a SecureRandom that can be fond in the registry. */ public void setSecureRandomName(String randomName) { if (context != null && randomName != null) { SecureRandom random = context.getRegistry().lookupByNameAndType(randomName, SecureRandom.class); if (keystore != null) { setSecureRandom(random); } } if (randomName != null) { this.secureRandomName = randomName; } } /** * Set the SecureRandom used to initialize the Signature service * * @param secureRandom the random used to init the Signature service */ public void setSecureRandom(SecureRandom secureRandom) { this.secureRandom = secureRandom; } /** * Get the size of the buffer used to read in the Exchange payload data. */ public Integer getBufferSize() { return bufferSize; } /** * Set the size of the buffer used to read in the Exchange payload data. */ public void setBufferSize(Integer bufferSize) { this.bufferSize = bufferSize; } /** * Get the id of the security provider that provides the configured * {@link Signature} algorithm. */ public String getProvider() { return provider; } /** * Set the id of the security provider that provides the configured * {@link Signature} algorithm. * * @param provider the id of the security provider */ public void setProvider(String provider) { this.provider = provider; } /** * Get the name of the message header that should be used to store the * base64 encoded signature. This defaults to 'CamelDigitalSignature' */ public String getSignatureHeaderName() { return signatureHeaderName != null ? signatureHeaderName : DigitalSignatureConstants.SIGNATURE; } /** * Set the name of the message header that should be used to store the * base64 encoded signature. This defaults to 'CamelDigitalSignature' */ public void setSignatureHeaderName(String signatureHeaderName) { this.signatureHeaderName = signatureHeaderName; } /** * Determines if the Signature specific headers be cleared after signing and * verification. Defaults to true, and should only be made otherwise at your * extreme peril as vital private information such as Keys and passwords may * escape if unset. * * @return true if the Signature headers should be unset, false otherwise */ public boolean isClearHeaders() { return clearHeaders; } /** * Determines if the Signature specific headers be cleared after signing and * verification. Defaults to true, and should only be made otherwise at your * extreme peril as vital private information such as Keys and passwords may * escape if unset. */ public void setClearHeaders(boolean clearHeaders) { this.clearHeaders = clearHeaders; } /** * Set the Crypto operation from that supplied after the crypto scheme in the * endpoint uri e.g. crypto:sign sets sign as the operation. * * @param operation the operation supplied after the crypto scheme */ public void setCryptoOperation(String operation) { this.cryptoOperation = CryptoOperation.valueOf(operation); } public void setCryptoOperation(CryptoOperation operation) { this.cryptoOperation = operation; } /** * Gets the Crypto operation that was supplied in the the crypto scheme in the endpoint uri */ public CryptoOperation getCryptoOperation() { return cryptoOperation; } }