B4J Library SSHJ - ssh, scp, sftp for Java

This is a wrapper for: https://github.com/hierynomus/sshj

Dependencies:
#AdditionalJar: slf4j-api-1.7.25
#AdditionalJar: sshj-0.23.0
#AdditionalJar: eddsa-0.2.0
#AdditionalJar: bcprov-jdk15on-159



You can download this libraries from:
slf4j-api-1.7.25: https://mvnrepository.com/artifact/org.slf4j/slf4j-api
sshj-0.23.0: https://mvnrepository.com/artifact/com.hierynomus/sshj
eddsa-0.2.0: https://mvnrepository.com/artifact/net.i2p.crypto/eddsa
(B4J) bcprov-jdk15on-159: https://www.bouncycastle.org/latest_releases.html
(B4A) prov-1.58.0.0.jar: https://mvnrepository.com/artifact/com.madgag.spongycastle/prov

*NOTE1* I tested this only with B4J, it should work for Android too!
*NOTE2* Also when running in Release you should set #MergeLibraries: False because of the bouncy castle dependency (bcprov-jdk15on-159) which is a signed jar, and when running with #MergeLibraries: True that jar is decompiled and compiled in your jar and therefore losses its signing.
*NOTE3* For Android you need to download spongy castle instead of bouncy castle. You can download it from https://mvnrepository.com/artifact/com.madgag.spongycastle/prov. I don't know if NOTE2 applies in this case.

First steps:
B4X:
    Dim ssh As SSHJ
    ssh.Initialize("ssh")
    '...... or ......
    ssh.Initialize2("ssh", 15) ' where 15 is the KeepAliveInterval - usefull for portforward and future sftp.
As connecting through ssh to a server wants to mean that is secure you have to add the server hostkey:
B4X:
ssh.LoadKnownHosts 'loads the known_hosts file from some default locations.
'or
ssh.LoadKnownHosts2("/tmp/known_hosts")
'or
ssh.AddHostKeyVerifier("SHA1:2Fo8c/96zv32xc8GZWbOGYOlRak=")
'or finnaly if you really trust the server and do not want to verify it's key
ssh.AddHostKeyPromiscuousVerifier
Next step is the authentication. You can supply multiple authentication methods:
B4X:
ssh.AddAuthPassword("youruserpass")
'or/and
ssh.AddAuthPublicKey("/location/to/my/key", "null if not encrypted")
'or/and
ssh.AddAuthPublicKey2("key-key-key-key...", "empty string if public key is in private key string", "null if not encrypted")
Finnaly now we connect:
B4X:
ssh.Connect("hostname/ip", 22, "yourusername")

All the execution methods (read details in ide) - Exec, Shell, SCPUpload, SCPDownload, LocalPortforwarder, RemotePortForwarder and all methods of SFTPClient - are async and work with Wait For feature of B4X.

Like always if you encounter problems i will do my best to help, but I'm no expert!

Edit by Erel: You need to add this line for it to work with the built-in packager:
B4X:
#PackagerProperty: VMArgs = --add-opens b4j/org.bouncycastle.jcajce.provider.asymmetric.ec=java.base
 

Attachments

  • SSHJ-v1.40.zip
    46.8 KB · Views: 1,103
Last edited by a moderator:

mindful

Active Member
Licensed User
Can someone test if this works with android too ?

It appears that on library github in the wiki page they have another configuration than the one provided with the library. In the current configuration I don't think it is necessary to include the eddsa-0.2.0.jar o_O
 

mindful

Active Member
Licensed User
This is because it's compiled with java 8 ... I will try to compile with java 7 - maybe it works ... and i will report back with a new java 7 version if the compilation will be successful.
 

mindful

Active Member
Licensed User
but it didn't work ... crashed
Please post some code and logs. As is mentioned in the 3rd post in the sshj github there is a page that explains how to make it work on android that is different from the current implementation of the library itself. so without seeing any code or logs I do not know for what to look.
 

Terence Agius

Member
Licensed User
Tried
Even with Android specific jar
Crashes


B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

#AdditionalJar: slf4j-api-1.7.25
'#AdditionalJar: sshj-0.23.0
#AdditionalJar: gradle-wrapper
'#AdditionalJar: eddsa-0.2.0
#AdditionalJar: bcpg-jdk15on-1.58.0.0

#BridgeLogger: True
'#MergeLibraries: False

'Activity module
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim ssh As SSHJ
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    'Dim SSH2 As jkSSH2
    
End Sub

Sub Activity_Create(FirstTime As Boolean)
  
   If FirstTime = True Then
        Log("Diable")
           DisableStrictMode
   End If
    ssh.Initialize2("ssh", 15)
    ssh.LoadKnownHosts
    ssh.AddHostKeyPromiscuousVerifier
    ssh.AddAuthPassword("password")
    ssh.Connect("192.168.10.18", 22, "root" )
    ssh.Exec("uname -a && date && uptime && who", 10)
    

End Sub

Sub Activity_Resume

End Sub

Sub DisableStrictMode
   Dim jo As JavaObject
   jo.InitializeStatic("android.os.Build.VERSION")
   If jo.GetField("SDK_INT") > 9 Then
     Dim policy As JavaObject
     policy = policy.InitializeNewInstance("android.os.StrictMode.ThreadPolicy.Builder", Null)
     policy = policy.RunMethodJO("permitAll", Null).RunMethodJO("build", Null)
     Dim sm As JavaObject
     sm.InitializeStatic("android.os.StrictMode").RunMethod("setThreadPolicy", Array(policy))
   End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub SSH_CmdExecuted (Success As Boolean, Result As List, TaskId As Int)
  
    Log (TaskId)
  
    If Success Then
        For i=0 To Result.Size-1
            Log(Result.Get(i) & CRLF)
        Next
    End If
  
    ssh.close
End Sub

Sub SSH_ConnectionLost (Reason As String)
    Log(Reason)
 

mindful

Active Member
Licensed User
'#AdditionalJar: sshj-0.23.0 -> You most definetly need this so uncomment it
'#AdditionalJar: eddsa-0.2.0 -> I am not sure if this is needed or not - you have to test

#MergeLibraries: False -> In b4j if you set False it doesn't pack the libraries inside the generated jar and they need to be copied manually near the jar.


You didn't post any logs ... so I have no ideea what to recommend :(

I will adventure in B4A soon and will be able to test this ...
 

Terence Agius

Member
Licensed User
#AdditionalJar: gradle-wrapper is sshj-0.23

and there are no logs that is why I didn't post any...the Log pane remains empty

#MergeLibraries does not work that is why its in a remark
 

LWGShane

Well-Known Member
Licensed User
Longtime User
I'm testing this library out and I can't connect to my server. The error message is:
B4X:
java.io.IOException: Could not load known_hosts
 

mindful

Active Member
Licensed User
@ShaneG30 ssh.LoadKnownHosts 'loads the known_hosts file from some default locations.

As connecting through ssh to a server wants to mean that is secure you have to add the server hostkey:
B4X:
ssh.LoadKnownHosts 'loads the known_hosts file from some default locations.
'or
ssh.LoadKnownHosts2("/tmp/known_hosts")
'or
ssh.AddHostKeyVerifier("SHA1:2Fo8c/96zv32xc8GZWbOGYOlRak=")
'or finnaly if you really trust the server and do not want to verify it's key
ssh.AddHostKeyPromiscuousVerifier

You should try using AddHostKeyPromiscuousVerifier ..
 

LWGShane

Well-Known Member
Licensed User
Longtime User
@mindful - I got it working and am connected to my server and it works wonderfully.
 

imbault

Well-Known Member
Licensed User
Longtime User
updated the library to version 1.31 (see first post). It's complete now as it includes a full featured SFTPClient.

Best regards,
Hi, could you send a sampled code using SFTP, please?

Thanks a lot

Patrick
 

mindful

Active Member
Licensed User
Hi, could you send a sampled code using SFTP, please?
Sure
B4X:
    Dim ssh As SSHJ
    ssh.Initialize2("ssh", 15)
    ssh.AddHostKeyPromiscuousVerifier
    ssh.AddAuthPassword("youruserpass")
    ssh.Connect("hostname/ip", 22, "yourusername")
   
    Dim sftp As SSHJSFTPClient = ssh.GetSFTPClient
   
    sftp.Upload("your-file-path", "server-file-path", False)

SFTP can be used for many thing besides file transfer between host and remote. You can find details in the ide at each method.
ide.png
 
Top