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.processor;
018    
019    import java.security.KeyStore;
020    import java.security.PrivateKey;
021    import java.security.SecureRandom;
022    import java.security.Signature;
023    import static java.lang.String.format;
024    
025    import org.apache.camel.Exchange;
026    import org.apache.camel.Message;
027    import org.apache.camel.component.crypto.DigitalSignatureConfiguration;
028    import org.apache.camel.component.crypto.DigitalSignatureConstants;
029    import org.apache.commons.codec.binary.Base64;
030    
031    import static org.apache.camel.component.crypto.DigitalSignatureConstants.SIGNATURE_PRIVATE_KEY;
032    
033    public class SigningProcessor extends DigitalSignatureProcessor {
034    
035        public SigningProcessor(DigitalSignatureConfiguration configuration) {
036            super(configuration);
037        }
038    
039        public void process(Exchange exchange) throws Exception {
040            Signature service = initSignatureService(exchange);
041            calculateSignature(exchange, service);
042            byte[] signature = service.sign();
043    
044            Message in = exchange.getIn();
045            clearMessageHeaders(in);
046            Message out = exchange.getOut();
047            out.copyFrom(in);
048            out.setHeader(config.getSignatureHeader(), new Base64().encode(signature));
049        }
050    
051        protected Signature initSignatureService(Exchange exchange) throws Exception {
052            PrivateKey pk = getPrivateKeyFromKeystoreOrExchange(exchange);
053            SecureRandom random = config.getSecureRandom();
054            Signature service = createSignatureService();
055            if (random != null) {
056                service.initSign(pk, random);
057            } else {
058                service.initSign(pk);
059            }
060            return service;
061        }
062    
063        private PrivateKey getPrivateKeyFromKeystoreOrExchange(Exchange exchange) throws Exception {
064            PrivateKey pk = config.getPrivateKey(getAlias(exchange), getKeyPassword(exchange));
065    
066            if (pk == null) {
067                pk = exchange.getIn().getHeader(SIGNATURE_PRIVATE_KEY, PrivateKey.class);
068                if (pk == null) {
069                    throw new IllegalStateException(format("Cannot sign message as no Private Key has been supplied. Either supply one in"
070                                                           + " the route definition sign(keystore, alias) or sign(privateKey) or via the message header '%s'", SIGNATURE_PRIVATE_KEY));
071                }
072            }
073            return pk;
074        }
075    
076        protected char[] getKeyPassword(Exchange exchange) throws Exception {
077            KeyStore keystore = config.getKeystore();
078            char[] password = null;
079            if (keystore != null) {
080                password = exchange.getIn().getHeader(DigitalSignatureConstants.KEYSTORE_PASSWORD, char[].class);
081                if (password == null) {
082                    password = config.getPassword();
083                }
084            }
085            return password;
086        }
087    }