001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.crypto;
018    
019    import java.security.KeyStore;
020    import java.security.PrivateKey;
021    import java.security.PublicKey;
022    import java.security.SecureRandom;
023    import java.security.Signature;
024    import java.security.cert.Certificate;
025    
026    import org.apache.camel.CamelContext;
027    import org.apache.camel.CamelContextAware;
028    import org.apache.camel.RuntimeCamelException;
029    
030    import static org.apache.camel.component.crypto.DigitalSignatureConstants.SIGNATURE;
031    
032    public class DigitalSignatureConfiguration implements Cloneable, CamelContextAware {
033    
034        private PrivateKey privateKey;
035        private KeyStore keystore;
036        private SecureRandom secureRandom;
037        private String algorithm = "DSA";
038        private Integer bufferSize = new Integer(2048);
039        private String provider;
040        private String signatureHeaderName;
041        private String alias;
042        private char[] password;
043        private PublicKey publicKey;
044        private Certificate certificate;
045        private CamelContext context;
046    
047        /** references that should be resolved when the context changes */
048        private String publicKeyName;
049        private String certificateName;
050        private String privateKeyName;
051        private String keystoreName;
052        private String randomName;
053        private boolean clearHeaders;
054        private String operation;
055    
056        public DigitalSignatureConfiguration copy() {
057            try {
058                return (DigitalSignatureConfiguration)clone();
059            } catch (CloneNotSupportedException e) {
060                throw new RuntimeCamelException(e);
061            }
062        }
063    
064        public CamelContext getCamelContext() {
065            return context;
066        }
067    
068        public void setCamelContext(CamelContext camelContext) {
069            this.context = camelContext;
070            // try to retrieve the references once the context is available.
071            setKeystore(keystoreName);
072            setPublicKey(publicKeyName);
073            setPrivateKey(privateKeyName);
074            setCertificate(certificateName);
075            setSecureRandom(randomName);
076        }
077    
078        /**
079         * Gets the JCE name of the Algorithm that should be used for the signer.
080         */
081        public String getAlgorithm() {
082            return algorithm;
083        }
084    
085        /**
086         * Sets the JCE name of the Algorithm that should be used for the signer.
087         */
088        public void setAlgorithm(String algorithm) {
089            this.algorithm = algorithm;
090        }
091    
092        /**
093         * Gets the alias used to query the KeyStore for keys and {@link java.security.cert.Certificate Certificates}
094         * to be used in signing and verifying exchanges. This value can be provided at runtime via the message header
095         * {@link org.apache.camel.component.crypto.DigitalSignatureConstants#KEYSTORE_ALIAS}
096         */
097        public String getAlias() {
098            return alias;
099        }
100    
101        /**
102         * Sets the alias used to query the KeyStore for keys and {@link java.security.cert.Certificate Certificates}
103         * to be used in signing and verifying exchanges. This value can be provided at runtime via the message header
104         * {@link org.apache.camel.component.crypto.DigitalSignatureConstants#KEYSTORE_ALIAS}
105         */
106        public void setAlias(String alias) {
107            this.alias = alias;
108        }
109    
110        /**
111         * Get the PrivateKey that should be used to sign the exchange
112         */
113        public PrivateKey getPrivateKey() throws Exception {
114            return getPrivateKey(alias, password);
115        }
116    
117        /**
118         * Get the PrivateKey that should be used to sign the signature in the
119         * exchange using the supplied alias.
120         *
121         * @param alias the alias used to retrieve the Certificate from the keystore.
122         */
123        public PrivateKey getPrivateKey(String alias) throws Exception {
124            return getPrivateKey(alias, password);
125        }
126    
127        /**
128         * Get the PrivateKey that should be used to sign the signature in the
129         * exchange using the supplied alias.
130         *
131         * @param alias the alias used to retrieve the Certificate from the keystore.
132         */
133        public PrivateKey getPrivateKey(String alias, char[] password) throws Exception {
134            PrivateKey pk = null;
135            if (alias != null && keystore != null) {
136                pk = (PrivateKey)keystore.getKey(alias, password);
137            }
138            if (pk == null) {
139                pk = privateKey;
140            }
141            return pk;
142        }
143    
144        /**
145         * Set the PrivateKey that should be used to sign the exchange
146         *
147         * @param privateKey the key with with to sign the exchange.
148         */
149        public void setPrivateKey(PrivateKey privateKey) {
150            this.privateKey = privateKey;
151        }
152    
153        /**
154         * Sets the reference name for a PrivateKey that can be fond in the registry.
155         */
156        public void setPrivateKey(String privateKeyName) {
157            if (context != null && privateKeyName != null) {
158                PrivateKey pk = context.getRegistry().lookup(privateKeyName, PrivateKey.class);
159                if (pk != null) {
160                    setPrivateKey(pk);
161                }
162            }
163            if (privateKeyName != null) {
164                this.privateKeyName = privateKeyName;
165            }
166        }
167    
168        /**
169         * Set the PublicKey that should be used to verify the signature in the exchange.
170         */
171        public void setPublicKey(PublicKey publicKey) {
172            this.publicKey = publicKey;
173        }
174    
175        /**
176         * Sets the reference name for a publicKey that can be fond in the registry.
177         */
178        public void setPublicKey(String publicKeyName) {
179            if (context != null && publicKeyName != null) {
180                PublicKey pk = context.getRegistry().lookup(publicKeyName, PublicKey.class);
181                if (pk != null) {
182                    setPublicKey(pk);
183                }
184            }
185            if (publicKeyName != null) {
186                this.publicKeyName = publicKeyName;
187            }
188        }
189    
190        /**
191         * get the PublicKey that should be used to verify the signature in the exchange.
192         */
193        public PublicKey getPublicKey() {
194            return publicKey;
195        }
196    
197        /**
198         * Set the Certificate that should be used to verify the signature in the
199         * exchange. If a {@link KeyStore} has been configured then this will
200         * attempt to retrieve the {@link Certificate}from it using hte supplied
201         * alias. If either the alias or the Keystore is invalid then the configured
202         * certificate will be returned
203         *
204         * @param alias the alias used to retrieve the Certificate from the keystore.
205         */
206        public Certificate getCertificate(String alias) throws Exception {
207            Certificate cert = null;
208            if (alias != null && keystore != null) {
209                cert = keystore.getCertificate(alias);
210            }
211            if (cert == null) {
212                cert = certificate;
213            }
214            return cert;
215        }
216    
217        /**
218         * Get the explicitly configured {@link Certificate} that should be used to
219         * verify the signature in the exchange.
220         */
221        public Certificate getCertificate() throws Exception {
222            return certificate;
223        }
224    
225        /**
226         * Set the Certificate that should be used to verify the signature in the
227         * exchange based on its payload.
228         */
229        public void setCertificate(Certificate certificate) {
230    
231            this.certificate = certificate;
232        }
233    
234        /**
235         * Sets the reference name for a PrivateKey that can be fond in the registry.
236         */
237        public void setCertificate(String certificateName) {
238            if (context != null && certificateName != null) {
239                Certificate certificate = context.getRegistry().lookup(certificateName, Certificate.class);
240                if (certificate != null) {
241                    setCertificate(certificate);
242                }
243            }
244            if (certificateName != null) {
245                this.certificateName = certificateName;
246            }
247        }
248    
249        /**
250         * Gets the KeyStore that can contain keys and Certficates for use in
251         * signing and verifying exchanges. A {@link KeyStore} is typically used
252         * with an alias, either one supplied in the Route definition or dynamically
253         * via the message header "CamelSignatureKeyStoreAlias". If no alias is
254         * supplied and there is only a single entry in the Keystore, then this
255         * single entry will be used.
256         */
257        public KeyStore getKeystore() {
258            return keystore;
259        }
260    
261        /**
262         * Sets the KeyStore that can contain keys and Certficates for use in
263         * signing and verifying exchanges. A {@link KeyStore} is typically used
264         * with an alias, either one supplied in the Route definition or dynamically
265         * via the message header "CamelSignatureKeyStoreAlias". If no alias is
266         * supplied and there is only a single entry in the Keystore, then this
267         * single entry will be used.
268         */
269        public void setKeystore(KeyStore keystore) {
270            this.keystore = keystore;
271        }
272    
273        /**
274         * Sets the reference name for a Keystore that can be fond in the registry.
275         */
276        public void setKeystore(String keystoreName) {
277            if (context != null && keystoreName != null) {
278                KeyStore keystore = context.getRegistry().lookup(keystoreName, KeyStore.class);
279                if (keystore != null) {
280                    setKeystore(keystore);
281                }
282            }
283            if (keystoreName != null) {
284                this.keystoreName = keystoreName;
285            }
286        }
287    
288        /**
289         * Gets the password used to access an aliased {@link PrivateKey} in the KeyStore.
290         */
291        public char[] getPassword() {
292            return password;
293        }
294    
295        /**
296         * Sets the password used to access an aliased {@link PrivateKey} in the KeyStore.
297         */
298        public void setPassword(char[] password) {
299            this.password = password;
300        }
301    
302        /**
303         * Get the SecureRandom used to initialize the Signature service
304         */
305        public SecureRandom getSecureRandom() {
306            return secureRandom;
307        }
308    
309        /**
310         * Sets the reference name for a SecureRandom that can be fond in the registry.
311         */
312        public void setSecureRandom(String randomName) {
313            if (context != null && randomName != null) {
314                SecureRandom random = context.getRegistry().lookup(randomName, SecureRandom.class);
315                if (keystore != null) {
316                    setSecureRandom(random);
317                }
318            }
319            if (randomName != null) {
320                this.randomName = randomName;
321            }
322        }
323    
324        /**
325         * Set the SecureRandom used to initialize the Signature service
326         *
327         * @param secureRandom the random used to init the Signature service
328         */
329        public void setSecureRandom(SecureRandom secureRandom) {
330            this.secureRandom = secureRandom;
331        }
332    
333        /**
334         * Get the size of the buffer used to read in the Exchange payload data.
335         */
336        public Integer getBufferSize() {
337            return bufferSize;
338        }
339    
340        /**
341         * Set the size of the buffer used to read in the Exchange payload data.
342         */
343        public void setBufferSize(Integer bufferSize) {
344            this.bufferSize = bufferSize;
345        }
346    
347        /**
348         * Get the id of the security provider that provides the configured
349         * {@link Signature} algorithm.
350         */
351        public String getProvider() {
352            return provider;
353        }
354    
355        /**
356         * Set the id of the security provider that provides the configured
357         * {@link Signature} algorithm.
358         *
359         * @param provider the id of the security provider
360         */
361        public void setProvider(String provider) {
362            this.provider = provider;
363        }
364    
365        /**
366         * Get the name of the message header that should be used to store the
367         * base64 encoded signature. This defaults to 'CamelDigitalSignature'
368         */
369        public String getSignatureHeader() {
370            return signatureHeaderName != null ? signatureHeaderName : SIGNATURE;
371        }
372    
373        /**
374         * Set the name of the message header that should be used to store the
375         * base64 encoded signature. This defaults to 'CamelDigitalSignature'
376         */
377        public void setSignatureHeader(String signatureHeaderName) {
378            this.signatureHeaderName = signatureHeaderName;
379        }
380    
381        /**
382         * Determines if the Signature specific headers be cleared after signing and
383         * verification. Defaults to true, and should only be made otherwise at your
384         * extreme peril as vital private information such as Keys and passwords may
385         * escape if unset.
386         *
387         * @return true if the Signature headers should be unset, false otherwise
388         */
389        public boolean getClearHeaders() {
390            return clearHeaders;
391        }
392    
393        /**
394         * Determines if the Signature specific headers be cleared after signing and
395         * verification. Defaults to true, and should only be made otherwise at your
396         * extreme peril as vital private information such as Keys and passwords may
397         * escape if unset.
398         */
399        public void setClearHeaders(boolean clearHeaders) {
400            this.clearHeaders = clearHeaders;
401        }
402    
403        /**
404         * Set the Crypto operation from that supplied after the crypto scheme in the
405         * endpoint uri e.g. crypto:sign sets sign as the operation.
406         *
407         * @param operation the operation supplied after the crypto scheme
408         */
409        public void setCryptoOperation(String operation) {
410            this.operation = operation;
411        }
412    
413        /**
414         * Gets the Crypto operation that was supplied in the the crypto scheme in the endpoint uri
415         */
416        public String getCryptoOperation() {
417            return operation;
418        }
419    }