Updated Branches:
  refs/heads/master 0afe60315 -> 2194a4de2

CAMEL-6502 Allow usage of Java KeyPair for SSH public key authentication in 
SFTP with thanks to Stephan


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/2194a4de
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/2194a4de
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/2194a4de

Branch: refs/heads/master
Commit: 2194a4de229aed8b02ee187fec92ef8a81b1d2ce
Parents: 0afe603
Author: Willem Jiang <ningji...@apache.org>
Authored: Tue Jul 2 17:33:46 2013 +0800
Committer: Willem Jiang <ningji...@apache.org>
Committed: Tue Jul 2 17:33:46 2013 +0800

----------------------------------------------------------------------
 .../file/remote/DSAKeyPairIdentity.java         | 228 +++++++++++++++++++
 .../file/remote/RSAKeyPairIdentity.java         | 146 ++++++++++++
 .../file/remote/SftpConfiguration.java          |  10 +
 .../component/file/remote/SftpOperations.java   |  21 ++
 .../remote/sftp/SftpKeyPairDSAConsumeTest.java  |  90 ++++++++
 .../remote/sftp/SftpKeyPairRSAConsumeTest.java  |  90 ++++++++
 6 files changed, 585 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/DSAKeyPairIdentity.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/DSAKeyPairIdentity.java
 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/DSAKeyPairIdentity.java
new file mode 100644
index 0000000..fa5cf11
--- /dev/null
+++ 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/DSAKeyPairIdentity.java
@@ -0,0 +1,228 @@
+/**
+ * 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.file.remote;
+
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+
+import com.jcraft.jsch.Identity;
+import com.jcraft.jsch.JSchException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DSAKeyPairIdentity implements Identity {
+    private static final String ALGORITHM_TYPE = "ssh-dss";
+    private final transient Logger log = LoggerFactory.getLogger(getClass());
+    private KeyPair keyPair;
+    private String name;
+
+    public DSAKeyPairIdentity(String name, KeyPair keyPair) {
+        this.name = name;
+        this.keyPair = keyPair;
+    }
+
+    @Override
+    public boolean setPassphrase(byte[] passphrase) throws JSchException {
+        return true;
+    }
+
+    @Override
+    public byte[] getPublicKeyBlob() {
+        DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();
+        byte[] sshDss = ALGORITHM_TYPE.getBytes();
+
+        DSAParams dsaParams = publicKey.getParams();
+        byte[] pArray = dsaParams.getP().toByteArray();
+        byte[] qArray = dsaParams.getQ().toByteArray();
+        byte[] gArray = dsaParams.getG().toByteArray();
+        byte[] yArray = publicKey.getY().toByteArray();
+
+        byte[] result = new byte[sshDss.length + 4 + pArray.length + 4 + 
qArray.length + 4 + gArray.length + 4 + yArray.length + 4];
+        int index = 0;
+
+        byte[] intAsByteArray = 
ByteBuffer.allocate(4).putInt(sshDss.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(sshDss, 0, result, index, sshDss.length);
+        index += sshDss.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(pArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(pArray, 0, result, index, pArray.length);
+        index += pArray.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(qArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(qArray, 0, result, index, qArray.length);
+        index += qArray.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(gArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(gArray, 0, result, index, gArray.length);
+        index += gArray.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(yArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(yArray, 0, result, index, yArray.length);
+
+        return result;
+    }
+
+    @Override
+    public byte[] getSignature(byte[] data) {
+        try {
+            PrivateKey prvKey = (PrivateKey) keyPair.getPrivate();
+            Signature sig;
+            sig = Signature.getInstance("SHA1withDSA");
+            sig.initSign(prvKey);
+            sig.update(data);
+            byte[] sshDss = ALGORITHM_TYPE.getBytes();
+            byte[] signature = sig.sign();
+
+            signature = convertDERToP1363(signature);
+
+            byte[] result = new byte[sshDss.length + 4 + signature.length + 4];
+            int index = 0;
+
+            byte[] intAsByteArray = 
ByteBuffer.allocate(4).putInt(sshDss.length).array();
+            System.arraycopy(intAsByteArray, 0, result, index, 4);
+            index += 4;
+
+            System.arraycopy(sshDss, 0, result, index, sshDss.length);
+            index += sshDss.length;
+
+            intAsByteArray = 
ByteBuffer.allocate(4).putInt(signature.length).array();
+            System.arraycopy(intAsByteArray, 0, result, index, 4);
+            index += 4;
+
+            System.arraycopy(signature, 0, result, index, signature.length);
+
+            return result;
+        } catch (NoSuchAlgorithmException e) {
+            log.error("Cannot sign", e);
+        } catch (InvalidKeyException e) {
+            log.error("Cannot sign", e);
+        } catch (SignatureException e) {
+            log.error("Cannot sign", e);
+        }
+        return null;
+    }
+
+    /**
+     * "The signature on m is (r, s). Message m and (r, s) should be sent to 
the
+     * verifier. We need to observe that both r and s are 20 bytes, since a
+     * modular reduction is being performed (steps 2 and 5) using q, a 160 bit
+     * value. This will gain significance later when we begin verifying 
messages
+     * between Crypto++ and C# (which use the IEEE P1363 signature format) and
+     * Java (which uses a DER encoding of a signature)." [taken from <a href=
+     * 
"http://www.codeproject.com/Articles/25590/Cryptographic-Interoperability-Digital-Signatures";
+     * >Cryptographic Interoperability Digital Signatures</a>]
+     * 
+     * @param sig
+     *            signature in DER format
+     * @return signature in P1363 format; SEQUENCE ::= { r INTEGER, s INTEGER }
+     */
+    private byte[] convertDERToP1363(byte[] sig) {
+        int index = 3;
+        int len = sig[index++] & 0xff;
+
+        byte[] r = new byte[len];
+        System.arraycopy(sig, index, r, 0, r.length);
+        index = index + len + 1;
+
+        len = sig[index++] & 0xff;
+        byte[] s = new byte[len];
+        System.arraycopy(sig, index, s, 0, s.length);
+
+        byte[] p1363Signature = new byte[40];
+        if (r.length > 21 || (r.length == 21 && r[0] != 0)) {
+            // Reject - signature verification failed
+        } else if (r.length == 21) {
+            // r[0] = 0
+            // r[1]'s high bit *should* be set
+            System.arraycopy(r, 1, p1363Signature, 0, 20);
+        } else if (r.length == 20) {
+            // r[0]'s high bit *should not* be set
+            System.arraycopy(r, 0, p1363Signature, 0, 20);
+        } else {
+            // fewer than 20 bytes
+            len = r.length;
+            int off = 20 - len;
+            System.arraycopy(r, 0, p1363Signature, off, len);
+        }
+
+        if (s.length > 21 || (s.length == 21 && s[0] != 0)) {
+            // Reject - signature verification failed
+            p1363Signature = new byte[0];
+        } else if (s.length == 21) {
+            // s[0] = 0
+            // s[1]'s high bit *should* be set
+            System.arraycopy(s, 1, p1363Signature, 20, 20);
+        } else if (s.length == 20) {
+            // s[0]'s high bit *should not* be set
+            System.arraycopy(s, 0, p1363Signature, 20, 20);
+        } else {
+            // fewer than 20 bytes
+            len = s.length;
+            int off = 40 - len;
+            System.arraycopy(s, 0, p1363Signature, off, len);
+        }
+
+        return p1363Signature;
+    }
+
+    @Override
+    public boolean decrypt() {
+        return true;
+    }
+
+    @Override
+    public String getAlgName() {
+        return ALGORITHM_TYPE;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean isEncrypted() {
+        return false;
+    }
+
+    @Override
+    public void clear() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RSAKeyPairIdentity.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RSAKeyPairIdentity.java
 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RSAKeyPairIdentity.java
new file mode 100644
index 0000000..fe5131b
--- /dev/null
+++ 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RSAKeyPairIdentity.java
@@ -0,0 +1,146 @@
+/**
+ * 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.file.remote;
+
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.RSAPublicKey;
+
+import com.jcraft.jsch.Identity;
+import com.jcraft.jsch.JSchException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+public class RSAKeyPairIdentity implements Identity {
+    private static final String ALGORITHM_TYPE = "ssh-rsa";
+    private final transient Logger log = LoggerFactory.getLogger(getClass());
+    
+    private KeyPair keyPair;
+    private String name;
+
+    public RSAKeyPairIdentity(String name, KeyPair keyPair) {
+        this.name = name;
+        this.keyPair = keyPair;
+    }
+
+    @Override
+    public boolean setPassphrase(byte[] passphrase) throws JSchException {
+        return true;
+    }
+
+    @Override
+    public byte[] getPublicKeyBlob() {
+        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
+        byte[] sshRsa = ALGORITHM_TYPE.getBytes();
+        byte[] eArray = publicKey.getPublicExponent().toByteArray();
+        byte[] nArray = publicKey.getModulus().toByteArray();
+
+        byte[] result = new byte[sshRsa.length + 4 + eArray.length + 4 + 
nArray.length + 4];
+        int index = 0;
+
+        byte[] intAsByteArray = 
ByteBuffer.allocate(4).putInt(sshRsa.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(sshRsa, 0, result, index, sshRsa.length);
+        index += sshRsa.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(eArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(eArray, 0, result, index, eArray.length);
+        index += eArray.length;
+
+        intAsByteArray = ByteBuffer.allocate(4).putInt(nArray.length).array();
+        System.arraycopy(intAsByteArray, 0, result, index, 4);
+        index += 4;
+
+        System.arraycopy(nArray, 0, result, index, nArray.length);
+
+        return result;
+    }
+
+    @Override
+    public byte[] getSignature(byte[] data) {
+        PrivateKey prvKey = keyPair.getPrivate();
+        Signature sig;
+        try {
+            sig = Signature.getInstance("SHA1withRSA");
+            sig.initSign(prvKey);
+            sig.update(data);
+            byte[] sshRsa = ALGORITHM_TYPE.getBytes();
+            byte[] signature = sig.sign();
+            byte[] result = new byte[sshRsa.length + 4 + signature.length + 4];
+            int index = 0;
+
+            byte[] intAsByteArray = 
ByteBuffer.allocate(4).putInt(sshRsa.length).array();
+            System.arraycopy(intAsByteArray, 0, result, index, 4);
+            index += 4;
+
+            System.arraycopy(sshRsa, 0, result, index, sshRsa.length);
+            index += sshRsa.length;
+
+            intAsByteArray = 
ByteBuffer.allocate(4).putInt(signature.length).array();
+            System.arraycopy(intAsByteArray, 0, result, index, 4);
+            index += 4;
+
+            System.arraycopy(signature, 0, result, index, signature.length);
+
+            return result;
+        } catch (NoSuchAlgorithmException e) {
+            log.error("Cannot sign", e);
+        } catch (InvalidKeyException e) {
+            log.error("Cannot sign", e);
+        } catch (SignatureException e) {
+            log.error("Cannot sign", e);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean decrypt() {
+        return true;
+    }
+
+    @Override
+    public String getAlgName() {
+        return ALGORITHM_TYPE;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean isEncrypted() {
+        return false;
+    }
+
+    @Override
+    public void clear() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConfiguration.java
 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConfiguration.java
index ebefc42..4569859 100644
--- 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConfiguration.java
+++ 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConfiguration.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.file.remote;
 
 import java.net.URI;
+import java.security.KeyPair;
 
 /**
  * Secure FTP configuration
@@ -31,6 +32,7 @@ public class SftpConfiguration extends 
RemoteFileConfiguration {
     private String privateKeyUri;
     private byte[] privateKey;
     private String privateKeyPassphrase;
+    private KeyPair keyPair;
     private String strictHostKeyChecking = "no";
     private int serverAliveInterval;
     private int serverAliveCountMax = 1;
@@ -119,6 +121,14 @@ public class SftpConfiguration extends 
RemoteFileConfiguration {
         this.privateKeyPassphrase = privateKeyFilePassphrase;
     }
 
+    public KeyPair getKeyPair() {
+        return keyPair;
+    }
+
+    public void setKeyPair(KeyPair keyPair) {
+        this.keyPair = keyPair;
+    }
+
     public String getStrictHostKeyChecking() {
         return strictHostKeyChecking;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
index a7ad773..cdf6e05 100644
--- 
a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
+++ 
b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
@@ -24,6 +24,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
+import java.security.KeyPair;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
@@ -203,6 +208,22 @@ public class SftpOperations implements 
RemoteFileOperations<ChannelSftp.LsEntry>
             }
         }
 
+        if (sftpConfig.getKeyPair() != null) {
+            LOG.debug("Using private key information from key pair");
+            KeyPair keyPair = sftpConfig.getKeyPair();
+            if (keyPair.getPrivate() != null && keyPair.getPublic() != null) {
+                if (keyPair.getPrivate() instanceof RSAPrivateKey && 
keyPair.getPublic() instanceof RSAPublicKey) {
+                    jsch.addIdentity(new RSAKeyPairIdentity("ID", keyPair), 
null);
+                } else if (keyPair.getPrivate() instanceof DSAPrivateKey && 
keyPair.getPublic() instanceof DSAPublicKey) {
+                    jsch.addIdentity(new DSAKeyPairIdentity("ID", keyPair), 
null);
+                } else {
+                    LOG.warn("Only RSA and DSA key pairs are supported");
+                }
+            } else {
+                LOG.warn("PrivateKey and PublicKey in the KeyPair must be 
filled");
+            }
+        }
+
         if (isNotEmpty(sftpConfig.getKnownHostsFile())) {
             LOG.debug("Using knownhosts file: {}", 
sftpConfig.getKnownHostsFile());
             jsch.setKnownHosts(sftpConfig.getKnownHostsFile());

http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairDSAConsumeTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairDSAConsumeTest.java
 
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairDSAConsumeTest.java
new file mode 100644
index 0000000..860a935
--- /dev/null
+++ 
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairDSAConsumeTest.java
@@ -0,0 +1,90 @@
+/**
+ * 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.file.remote.sftp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.util.IOHelper;
+import org.junit.Test;
+
+public class SftpKeyPairDSAConsumeTest extends SftpServerTestSupport {
+
+    @Test
+    public void testSftpSimpleConsume() throws Exception {
+        if (!canTest()) {
+            return;
+        }
+
+        String expected = "Hello World";
+
+        // create file using regular file
+        template.sendBodyAndHeader("file://" + FTP_ROOT_DIR, expected, 
Exchange.FILE_NAME, "hello.txt");
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(Exchange.FILE_NAME, "hello.txt");
+        mock.expectedBodiesReceived(expected);
+
+        context.startRoute("foo");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    private byte[] getBytesFromFile(String filename) throws IOException {
+        InputStream input;
+        input = new FileInputStream(new File(filename));
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        IOHelper.copyAndCloseInput(input, output);
+        return output.toByteArray();
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
+        keyGen.initialize(1024);
+        KeyPair pair = keyGen.generateKeyPair();
+        registry.bind("keyPair", pair);
+        registry.bind("knownHosts", 
getBytesFromFile("./src/test/resources/known_hosts"));
+
+        return registry;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("sftp://localhost:"; + getPort() + "/" + FTP_ROOT_DIR
+                        + 
"?username=admin&knownHosts=#knownHosts&keyPair=#keyPair&delay=10s&strictHostKeyChecking=yes&disconnect=true")
+                    .routeId("foo").noAutoStartup()
+                    .to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/2194a4de/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairRSAConsumeTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairRSAConsumeTest.java
 
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairRSAConsumeTest.java
new file mode 100644
index 0000000..4ecd089
--- /dev/null
+++ 
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpKeyPairRSAConsumeTest.java
@@ -0,0 +1,90 @@
+/**
+ * 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.file.remote.sftp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.util.IOHelper;
+import org.junit.Test;
+
+public class SftpKeyPairRSAConsumeTest extends SftpServerTestSupport {
+
+    @Test
+    public void testSftpSimpleConsume() throws Exception {
+        if (!canTest()) {
+            return;
+        }
+
+        String expected = "Hello World";
+
+        // create file using regular file
+        template.sendBodyAndHeader("file://" + FTP_ROOT_DIR, expected, 
Exchange.FILE_NAME, "hello.txt");
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(Exchange.FILE_NAME, "hello.txt");
+        mock.expectedBodiesReceived(expected);
+
+        context.startRoute("foo");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    private byte[] getBytesFromFile(String filename) throws IOException {
+        InputStream input;
+        input = new FileInputStream(new File(filename));
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        IOHelper.copyAndCloseInput(input, output);
+        return output.toByteArray();
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(2048);
+        KeyPair pair = keyGen.generateKeyPair();
+        registry.bind("keyPair", pair);
+        registry.bind("knownHosts", 
getBytesFromFile("./src/test/resources/known_hosts"));
+
+        return registry;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("sftp://localhost:"; + getPort() + "/" + FTP_ROOT_DIR
+                        + 
"?username=admin&knownHosts=#knownHosts&keyPair=#keyPair&delay=10s&strictHostKeyChecking=yes&disconnect=true")
+                    .routeId("foo").noAutoStartup()
+                    .to("mock:result");
+            }
+        };
+    }
+}

Reply via email to