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