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 */
017package org.apache.camel.model.dataformat;
018
019import java.util.HashMap;
020import java.util.Map;
021import javax.xml.bind.annotation.XmlAccessType;
022import javax.xml.bind.annotation.XmlAccessorType;
023import javax.xml.bind.annotation.XmlAttribute;
024import javax.xml.bind.annotation.XmlRootElement;
025import javax.xml.bind.annotation.XmlTransient;
026
027import org.apache.camel.CamelContext;
028import org.apache.camel.model.DataFormatDefinition;
029import org.apache.camel.spi.DataFormat;
030import org.apache.camel.spi.Metadata;
031import org.apache.camel.spi.NamespaceAware;
032import org.apache.camel.util.jsse.KeyStoreParameters;
033
034/**
035 * The XML Security data format facilitates encryption and decryption of XML payloads.
036 */
037@Metadata(firstVersion = "2.0.0", label = "dataformat,transformation,xml,security", title = "XML Security")
038@XmlRootElement(name = "secureXML")
039@XmlAccessorType(XmlAccessType.FIELD)
040public class XMLSecurityDataFormat extends DataFormatDefinition implements NamespaceAware {
041
042    private static final String TRIPLEDES = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc";
043
044    @XmlAttribute @Metadata(defaultValue = "TRIPLEDES")
045    private String xmlCipherAlgorithm;
046    @XmlAttribute
047    private String passPhrase;
048    @XmlAttribute
049    private String secureTag;
050    @XmlAttribute
051    private Boolean secureTagContents;
052    @XmlAttribute  @Metadata(defaultValue = "RSA_OAEP")
053    private String keyCipherAlgorithm;
054    @XmlAttribute
055    private String recipientKeyAlias;
056    @XmlAttribute
057    // TODO: rename to keyOrTrustStoreParametersRef
058    private String keyOrTrustStoreParametersId;
059    @XmlAttribute
060    private String keyPassword;
061    @XmlAttribute  @Metadata(defaultValue = "SHA1")
062    private String digestAlgorithm;
063    @XmlAttribute  @Metadata(defaultValue = "MGF1_SHA1")
064    private String mgfAlgorithm;
065    @XmlAttribute @Metadata(defaultValue = "true")
066    private Boolean addKeyValueForEncryptedKey;
067    @XmlTransient
068    private KeyStoreParameters keyOrTrustStoreParameters;
069    @XmlTransient
070    private Map<String, String> namespaces;
071
072    public XMLSecurityDataFormat() {
073        super("secureXML");
074    }
075
076    // all the parameter constructors is deprecated as people should use getter/setter to configure
077
078    @Deprecated
079    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents) {
080        this();
081        this.setSecureTag(secureTag);
082        this.setSecureTagContents(secureTagContents);
083    }
084
085    @Deprecated
086    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents) {
087        this();
088        this.setSecureTag(secureTag);
089        this.setSecureTagContents(secureTagContents);
090        this.setNamespaces(namespaces);
091    }
092
093    @Deprecated
094    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String passPhrase) {
095        this(secureTag, secureTagContents);
096        this.setPassPhrase(passPhrase);
097    }
098
099    @Deprecated
100    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents,
101                                 String passPhrase) {
102        this(secureTag, secureTagContents);
103        this.setPassPhrase(passPhrase);
104        this.setNamespaces(namespaces);
105    }
106
107    @Deprecated
108    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String passPhrase,
109                                 String xmlCipherAlgorithm) {
110        this(secureTag, secureTagContents, passPhrase);
111        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
112    }
113
114    @Deprecated
115    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String passPhrase,
116                                 String xmlCipherAlgorithm) {
117        this(secureTag, secureTagContents, passPhrase);
118        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
119        this.setNamespaces(namespaces);
120    }
121    
122    /**
123     * @deprecated  use {{@link #XMLSecurityDataFormat(String, boolean, String, String, String, String)} or 
124     *                  {{@link #XMLSecurityDataFormat(String, boolean, String, String, String, KeyStoreParameters)} instead
125     */
126    @Deprecated
127    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias,
128            String xmlCipherAlgorithm, String keyCipherAlgorithm) {
129        this(secureTag, secureTagContents);
130        this.setRecipientKeyAlias(recipientKeyAlias);
131        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
132        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
133    }
134
135    @Deprecated
136    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias,
137                                 String xmlCipherAlgorithm, String keyCipherAlgorithm, String keyOrTrustStoreParametersId) {
138        this(secureTag, secureTagContents);
139        this.setRecipientKeyAlias(recipientKeyAlias);
140        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
141        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
142        this.setKeyOrTrustStoreParametersId(keyOrTrustStoreParametersId);
143    }
144
145    @Deprecated
146    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias,
147            String xmlCipherAlgorithm, String keyCipherAlgorithm, KeyStoreParameters keyOrTrustStoreParameters) {
148        this(secureTag, secureTagContents);
149        this.setRecipientKeyAlias(recipientKeyAlias);
150        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
151        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
152        this.setKeyOrTrustStoreParameters(keyOrTrustStoreParameters);
153    }
154
155    @Deprecated
156    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias,
157            String xmlCipherAlgorithm, String keyCipherAlgorithm, String keyOrTrustStoreParametersId, String keyPassword) {
158        this(secureTag, secureTagContents);
159        this.setRecipientKeyAlias(recipientKeyAlias);
160        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
161        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
162        this.setKeyOrTrustStoreParametersId(keyOrTrustStoreParametersId);
163        this.setKeyPassword(keyPassword);
164    }
165
166    @Deprecated
167    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias,
168        String xmlCipherAlgorithm, String keyCipherAlgorithm, KeyStoreParameters keyOrTrustStoreParameters, String keyPassword) {
169        this(secureTag, secureTagContents);
170        this.setRecipientKeyAlias(recipientKeyAlias);
171        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
172        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
173        this.setKeyOrTrustStoreParameters(keyOrTrustStoreParameters);
174        this.setKeyPassword(keyPassword);
175    }
176    
177    /**
178     * @deprecated  use {{@link #XMLSecurityDataFormat(String, Map, boolean, String, String, String, String)} or 
179     *                  {{@link #XMLSecurityDataFormat(String, Map, boolean, String, String, String, KeyStoreParameters)} instead
180     */
181    @Deprecated
182    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
183            String xmlCipherAlgorithm, String keyCipherAlgorithm) {
184        this(secureTag, secureTagContents);
185        this.setRecipientKeyAlias(recipientKeyAlias);
186        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
187        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
188        this.setNamespaces(namespaces);
189    }
190
191    @Deprecated
192    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
193            String xmlCipherAlgorithm, String keyCipherAlgorithm, String keyOrTrustStoreParametersId) {
194        this(secureTag, secureTagContents);
195        this.setRecipientKeyAlias(recipientKeyAlias);
196        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
197        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
198        this.setNamespaces(namespaces);
199        this.setKeyOrTrustStoreParametersId(keyOrTrustStoreParametersId);
200    }
201
202    @Deprecated
203    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
204            String xmlCipherAlgorithm, String keyCipherAlgorithm, KeyStoreParameters keyOrTrustStoreParameters) {
205        this(secureTag, secureTagContents);
206        this.setRecipientKeyAlias(recipientKeyAlias);
207        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
208        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
209        this.setNamespaces(namespaces);
210        this.setKeyOrTrustStoreParameters(keyOrTrustStoreParameters);
211    }
212
213    @Deprecated
214    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
215            String xmlCipherAlgorithm, String keyCipherAlgorithm, String keyOrTrustStoreParametersId, String keyPassword) {
216        this(secureTag, secureTagContents);
217        this.setRecipientKeyAlias(recipientKeyAlias);
218        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
219        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
220        this.setNamespaces(namespaces);
221        this.setKeyOrTrustStoreParametersId(keyOrTrustStoreParametersId);
222        this.setKeyPassword(keyPassword);
223    }
224
225    @Deprecated
226    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
227            String xmlCipherAlgorithm, String keyCipherAlgorithm, KeyStoreParameters keyOrTrustStoreParameters, String keyPassword) {
228        this(secureTag, secureTagContents);
229        this.setRecipientKeyAlias(recipientKeyAlias);
230        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
231        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
232        this.setNamespaces(namespaces);
233        this.setKeyOrTrustStoreParameters(keyOrTrustStoreParameters);
234        this.setKeyPassword(keyPassword);
235    }
236
237    @Deprecated
238    public XMLSecurityDataFormat(String secureTag, Map<String, String> namespaces, boolean secureTagContents, String recipientKeyAlias,
239             String xmlCipherAlgorithm, String keyCipherAlgorithm, KeyStoreParameters keyOrTrustStoreParameters, String keyPassword,
240             String digestAlgorithm) {
241        this(secureTag, secureTagContents);
242        this.setRecipientKeyAlias(recipientKeyAlias);
243        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
244        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
245        this.setNamespaces(namespaces);
246        this.setKeyOrTrustStoreParameters(keyOrTrustStoreParameters);
247        this.setKeyPassword(keyPassword);
248        this.setDigestAlgorithm(digestAlgorithm);
249    }
250
251    @Override
252    protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) {
253        if (getSecureTag() != null) {
254            setProperty(camelContext, dataFormat, "secureTag", getSecureTag());
255        } else {
256            setProperty(camelContext, dataFormat, "secureTag", "");
257        }
258
259        boolean isSecureTagContents = getSecureTagContents() != null && getSecureTagContents();
260        setProperty(camelContext, dataFormat, "secureTagContents", isSecureTagContents);
261
262        if (passPhrase != null) {
263            setProperty(camelContext, dataFormat, "passPhrase", getPassPhrase().getBytes());
264        } else {
265            setProperty(camelContext, dataFormat, "passPhrase", "Just another 24 Byte key".getBytes());
266        }
267        if (getXmlCipherAlgorithm() != null) {
268            setProperty(camelContext, dataFormat, "xmlCipherAlgorithm", getXmlCipherAlgorithm());
269        } else {
270            setProperty(camelContext, dataFormat, "xmlCipherAlgorithm", TRIPLEDES);
271        }
272        if (getKeyCipherAlgorithm() != null) {
273            setProperty(camelContext, dataFormat, "keyCipherAlgorithm", getKeyCipherAlgorithm());
274        }
275        if (getRecipientKeyAlias() != null) {
276            setProperty(camelContext, dataFormat, "recipientKeyAlias", getRecipientKeyAlias());
277        }
278        if (getKeyOrTrustStoreParametersId() != null) {
279            setProperty(camelContext, dataFormat, "keyOrTrustStoreParametersId", getKeyOrTrustStoreParametersId());
280        }
281        if (keyOrTrustStoreParameters != null) {
282            setProperty(camelContext, dataFormat, "keyOrTrustStoreParameters", this.keyOrTrustStoreParameters);
283        }
284        if (namespaces != null) {
285            setProperty(camelContext, dataFormat, "namespaces", this.namespaces);
286        }
287        if (keyPassword != null) {
288            setProperty(camelContext, dataFormat, "keyPassword", this.getKeyPassword());
289        }
290        if (digestAlgorithm != null) {
291            setProperty(camelContext, dataFormat, "digestAlgorithm", this.getDigestAlgorithm());
292        }
293        if (mgfAlgorithm != null) {
294            setProperty(camelContext, dataFormat, "mgfAlgorithm", this.getMgfAlgorithm());
295        }
296        // should be true by default
297        boolean isAddKeyValueForEncryptedKey = getAddKeyValueForEncryptedKey() == null || getAddKeyValueForEncryptedKey();
298        setProperty(camelContext, dataFormat, "addKeyValueForEncryptedKey", isAddKeyValueForEncryptedKey);
299    }
300
301    public String getXmlCipherAlgorithm() {
302        return xmlCipherAlgorithm;
303    }
304
305    /**
306     * The cipher algorithm to be used for encryption/decryption of the XML message content. The available choices are:
307     * <ul>
308     *     <li>XMLCipher.TRIPLEDES</li>
309     *     <li>XMLCipher.AES_128</li>
310     *     <li>XMLCipher.AES_128_GCM</li>
311     *     <li>XMLCipher.AES_192</li>
312     *     <li>XMLCipher.AES_192_GCM</li>
313     *     <li>XMLCipher.AES_256</li>
314     *     <li>XMLCipher.AES_256_GCM</li>
315     *     <li>XMLCipher.SEED_128</li>
316     *     <li>XMLCipher.CAMELLIA_128</li>
317     *     <li>XMLCipher.CAMELLIA_192</li>
318     *     <li>XMLCipher.CAMELLIA_256</li>
319     * </ul>
320     * The default value is MLCipher.TRIPLEDES
321     */
322    public void setXmlCipherAlgorithm(String xmlCipherAlgorithm) {
323        this.xmlCipherAlgorithm = xmlCipherAlgorithm;
324    }
325
326    public String getPassPhrase() {
327        return passPhrase;
328    }
329
330    /**
331     * A String used as passPhrase to encrypt/decrypt content. The passPhrase has to be provided.
332     * If no passPhrase is specified, a default passPhrase is used.
333     * The passPhrase needs to be put together in conjunction with the appropriate encryption algorithm.
334     * For example using TRIPLEDES the passPhase can be a "Only another 24 Byte key"
335     */
336    public void setPassPhrase(String passPhrase) {
337        this.passPhrase = passPhrase;
338    }
339
340    public String getSecureTag() {
341        return secureTag;
342    }
343
344    /**
345     * The XPath reference to the XML Element selected for encryption/decryption. If no tag is specified, the entire payload is encrypted/decrypted.
346     */
347    public void setSecureTag(String secureTag) {
348        this.secureTag = secureTag;
349    }
350
351    public Boolean getSecureTagContents() {
352        return secureTagContents;
353    }
354
355    /**
356     * A boolean value to specify whether the XML Element is to be encrypted or the contents of the XML Element
357     * false = Element Level
358     * true = Element Content Level
359     */
360    public void setSecureTagContents(Boolean secureTagContents) {
361        this.secureTagContents = secureTagContents;
362    }
363
364    /**
365     * The cipher algorithm to be used for encryption/decryption of the asymmetric key. The available choices are:
366     * <ul>
367     *     <li>XMLCipher.RSA_v1dot5</li>
368     *     <li>XMLCipher.RSA_OAEP</li>
369     *     <li>XMLCipher.RSA_OAEP_11</li>
370     * </ul>
371     * The default value is XMLCipher.RSA_OAEP
372     */
373    public void setKeyCipherAlgorithm(String keyCipherAlgorithm) {
374        this.keyCipherAlgorithm = keyCipherAlgorithm;
375    }
376
377    public String getKeyCipherAlgorithm() {
378        return keyCipherAlgorithm;
379    }
380
381    /**
382     * The key alias to be used when retrieving the recipient's public or private key from a KeyStore when performing asymmetric key encryption or decryption.
383     */
384    public void setRecipientKeyAlias(String recipientKeyAlias) {
385        this.recipientKeyAlias = recipientKeyAlias;
386    }
387
388    public String getRecipientKeyAlias() {
389        return recipientKeyAlias;
390    }
391
392    /**
393     * Refers to a KeyStore instance to lookup in the registry, which is used for
394     * configuration options for creating and loading a KeyStore instance that represents the sender's trustStore or recipient's keyStore.
395     */
396    public void setKeyOrTrustStoreParametersId(String id) {
397        this.keyOrTrustStoreParametersId = id;
398    }
399    
400    public String getKeyOrTrustStoreParametersId() {
401        return this.keyOrTrustStoreParametersId;
402    }
403
404    public KeyStoreParameters getKeyOrTrustStoreParameters() {
405        return keyOrTrustStoreParameters;
406    }
407
408    /**
409     * Configuration options for creating and loading a KeyStore instance that represents the sender's trustStore or recipient's keyStore.
410     */
411    private void setKeyOrTrustStoreParameters(KeyStoreParameters keyOrTrustStoreParameters) {
412        this.keyOrTrustStoreParameters = keyOrTrustStoreParameters;
413    }
414    
415    public String getKeyPassword() {
416        return this.keyPassword;
417    }
418
419    /**
420     * The password to be used for retrieving the private key from the KeyStore. This key is used for asymmetric decryption.
421     */
422    public void setKeyPassword(String keyPassword) {
423        this.keyPassword = keyPassword;
424    }
425
426    public String getDigestAlgorithm() {
427        return digestAlgorithm;
428    }
429
430    /**
431     * The digest algorithm to use with the RSA OAEP algorithm. The available choices are:
432     * <ul>
433     *     <li>XMLCipher.SHA1</li>
434     *     <li>XMLCipher.SHA256</li>
435     *     <li>XMLCipher.SHA512</li>
436     * </ul>
437     * The default value is XMLCipher.SHA1
438     */
439    public void setDigestAlgorithm(String digestAlgorithm) {
440        this.digestAlgorithm = digestAlgorithm;
441    }
442
443    public String getMgfAlgorithm() {
444        return mgfAlgorithm;
445    }
446
447    /**
448     * The MGF Algorithm to use with the RSA OAEP algorithm. The available choices are:
449     * <ul>
450     *     <li>EncryptionConstants.MGF1_SHA1</li>
451     *     <li>EncryptionConstants.MGF1_SHA256</li>
452     *     <li>EncryptionConstants.MGF1_SHA512</li>
453     * </ul>
454     * The default value is EncryptionConstants.MGF1_SHA1
455     */
456    public void setMgfAlgorithm(String mgfAlgorithm) {
457        this.mgfAlgorithm = mgfAlgorithm;
458    }
459
460    public Boolean getAddKeyValueForEncryptedKey() {
461        return addKeyValueForEncryptedKey;
462    }
463
464    /**
465     * Whether to add the public key used to encrypt the session key as a KeyValue in the EncryptedKey structure or not.
466     */
467    public void setAddKeyValueForEncryptedKey(Boolean addKeyValueForEncryptedKey) {
468        this.addKeyValueForEncryptedKey = addKeyValueForEncryptedKey;
469    }
470
471    @Override
472    public void setNamespaces(Map<String, String> nspaces) {
473        if (this.namespaces == null) {
474            this.namespaces = new HashMap<>();
475        }
476        this.namespaces.putAll(nspaces);
477    }
478
479    @Override
480    public Map<String, String> getNamespaces() {
481        return namespaces;
482    }
483}