Compare commits

..

1 Commits

Author SHA1 Message Date
hierynomus
936c6c8008 v0.11.0 2015-01-23 10:01:50 +01:00
379 changed files with 5030 additions and 17430 deletions

View File

@@ -1,8 +0,0 @@
exclude:
- /build-publishing.gradle
- /build.gradle
- /settings.gradle
component_depth: 1
languages:
- groovy
- java

2
.github/CODEOWNERS vendored
View File

@@ -1,2 +0,0 @@
* @hierynomus

View File

@@ -1,55 +0,0 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Build SSHJ
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
java8:
name: Build with Java 8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew check
java9:
name: Build with Java 9
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 9
uses: actions/setup-java@v1
with:
java-version: 9
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew check -xanimalsnifferMain -xanimalsnifferTest
integration:
name: Integration test
needs: [java8]
runs-on: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- uses: actions/setup-java@v1
with:
java-version: 8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew integrationTest

8
.gitignore vendored
View File

@@ -10,14 +10,8 @@
.settings/
# Output dirs
out/
target/
classes/
bin/
build/
docs/
.gradle/
sshj.jar
# MacOS X
.DS_Store

View File

@@ -1,30 +1 @@
language: java
dist: trusty
sudo: required
services:
- docker
jdk:
- oraclejdk8
- openjdk8
- oraclejdk9
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
before_install:
- pip install --user codecov
script:
- ./gradlew check
- ./gradlew integrationTest
after_success:
- codecov
language: java

View File

@@ -1,13 +0,0 @@
Copyright (C)2009 - SSHJ Contributors
Licensed 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.

2
NOTICE
View File

@@ -15,7 +15,7 @@ The Apache Software Foundation (http://www.apache.org/):
== in this case for the SSHD distribution. ==
=========================================================================
This product contains software developed by JCraft,Inc. and subject to
This product contains software developped by JCraft,Inc. and subject to
the following license:
Copyright (c) 2002,2003,2004,2005,2006,2007,2008 Atsuhiko Yamanaka, JCraft,Inc.

View File

@@ -1,15 +1,10 @@
= sshj - SSHv2 library for Java
Jeroen van Erp
:sshj_groupid: com.hierynomus
:sshj_version: 0.28.0
:sshj_version: 0.11.0
:source-highlighter: pygments
image:https://api.bintray.com/packages/hierynomus/maven/sshj/images/download.svg[link="https://bintray.com/hierynomus/maven/sshj/_latestVersion"]
image:https://travis-ci.org/hierynomus/sshj.svg?branch=master[link="https://travis-ci.org/hierynomus/sshj"]
image:https://api.codacy.com/project/badge/Grade/14a0a316bb9149739b5ea26dbfa8da8a["Codacy code quality", link="https://www.codacy.com/app/jeroen_2/sshj?utm_source=github.com&utm_medium=referral&utm_content=hierynomus/sshj&utm_campaign=Badge_Grade"]
image:https://codecov.io/gh/hierynomus/sshj/branch/master/graph/badge.svg["codecov", link="https://codecov.io/gh/hierynomus/sshj"]
image:http://www.javadoc.io/badge/com.hierynomus/sshj.svg?color=blue["JavaDocs", link="http://www.javadoc.io/doc/com.hierynomus/sshj"]
image:https://maven-badges.herokuapp.com/maven-central/com.hierynomus/sshj/badge.svg["Maven Central",link="https://maven-badges.herokuapp.com/maven-central/com.hierynomus/sshj"]
image::https://travis-ci.org/hierynomus/sshj.svg?branch=master[]
To get started, have a look at one of the examples. Hopefully you will find the API pleasant to work with :)
@@ -39,7 +34,7 @@ If you're building your project using Maven, you can add the following dependenc
If your project is built using another build tool that uses the Maven Central repository, translate this dependency into the format used by your build tool.
== Building SSHJ
. Clone the SSHJ repository.
. Clone the Overthere repository.
. Ensure you have Java6 installed with the http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html[Unlimited strength Java Cryptography Extensions (JCE)].
. Run the command `./gradlew clean build`.
@@ -64,36 +59,25 @@ In the `examples` directory, there is a separate Maven project that shows how th
Implementations / adapters for the following algorithms are included:
ciphers::
`aes{128,192,256}-{cbc,ctr}`, `blowfish-{cbc,ctr}`, `3des-{cbc,ctr}`, `twofish{128,192,256}-{cbc,ctr}`, `twofish-cbc`, `serpent{128,192,256}-{cbc,ctr}`, `idea-{cbc,ctr}`, `cast128-{cbc,ctr}`, `arcfour`, `arcfour{128,256}`
SSHJ also supports the following extended (non official) ciphers: `camellia{128,192,256}-{cbc,ctr}`, `camellia{128,192,256}-{cbc,ctr}@openssh.org`
`aes{128,192,256}-{cbc,ctr}`, `blowfish-cbc`, `3des-cbc`
key exchange::
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`,
`diffie-hellman-group14-sha256`, `diffie-hellman-group15-sha512`, `diffie-hellman-group16-sha512`, `diffie-hellman-group17-sha512`, `diffie-hellman-group18-sha512`
`diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
`ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
SSHJ also supports the following extended (non official) key exchange algorithms:
`diffie-hellman-group14-sha256@ssh.com`, `diffie-hellman-group15-sha256`, `diffie-hellman-group15-sha256@ssh.com`, `diffie-hellman-group15-sha384@ssh.com`,
`diffie-hellman-group16-sha256`, `diffie-hellman-group16-sha384@ssh.com`, `diffie-hellman-group16-sha512@ssh.com`, `diffie-hellman-group18-sha512@ssh.com`
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`
signatures::
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`
`ssh-rsa`, `ssh-dss`
mac::
`hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`, `hmac-ripemd160`, `hmac-ripemd160@openssh.com`
`hmac-md5-etm@openssh.com`, `hmac-md5-96-etm@openssh.com`, `hmac-sha1-etm@openssh.com`, `hmac-sha1-96-etm@openssh.com`, `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-512-etm@openssh.com`, `hmac-ripemd160-etm@openssh.com`
`hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`
compression::
`zlib` and `zlib@openssh.com` (delayed zlib)
private key files::
`pkcs5`, `pkcs8`, `openssh-key-v1`, `ssh-rsa-cert-v01@openssh.com`, `ssh-dsa-cert-v01@openssh.com`
`pkcs8` encoded (what openssh uses)
If you need something that is not included, it shouldn't be too hard to add (do contribute it!)
== Comparing to other implementations
http://ssh-comparison.quendi.de/comparison.html[SSH Implementation Comparison]
== Dependencies
Java 6+. http://www.slf4j.org/download.html[slf4j] is required. http://www.bouncycastle.org/java.html[bouncycastle] is highly recommended and required for using some of the crypto algorithms. http://www.jcraft.com/jzlib/[jzlib] is required for using zlib compression.
@@ -101,115 +85,15 @@ Java 6+. http://www.slf4j.org/download.html[slf4j] is required. http://www.bounc
== Reporting bugs
Issue tracker: https://github.com/hierynomus/sshj/issues
== Discussion
Google Group: http://groups.google.com/group/sshj-users
== Contributing
Fork away!
== Release history
SSHJ 0.27.0 (2019-01-24)::
* Fixed https://github.com/hierynomus/sshj/issues/415[#415]: Fixed wrongly prefixed '/' to path in SFTPClient.mkdirs
* Added support for ETM (Encrypt-then-Mac) MAC algorithms.
* Fixed https://github.com/hierynomus/sshj/issues/454[#454]: Added missing capacity check for Buffer.putUint64
* Fixed https://github.com/hierynomus/sshj/issues/466[#466]: Added lock timeout for remote action to prevent hanging
* Fixed https://github.com/hierynomus/sshj/issues/470[#470]: Made EdDSA the default (first) signature factory
* Fixed https://github.com/hierynomus/sshj/issues/467[#467]: Added AES256-CBC as cipher mode in openssh-key-v1 support
* Fixed https://github.com/hierynomus/sshj/issues/464[#464]: Enabled curve25519-sha256@openssh.org in DefaultConfig
* Fixed https://github.com/hierynomus/sshj/issues/472[#472]: Handle server initiated global requests
* Fixed https://github.com/hierynomus/sshj/issues/485[#485]: Added support for all keytypes to openssh-key-v1 keyfiles.
SSHJ 0.26.0 (2018-07-24)::
* Fixed https://github.com/hierynomus/sshj/issues/413[#413]: Use UTF-8 for PrivateKeyFileResource
* Fixed https://github.com/hierynomus/sshj/issues/427[#427]: Support encrypted ed25519 openssh-key-v1 files
* Upgraded BouncyCastle to 1.60
* Added support for hmac-ripemd160@openssh.com MAC
SSHJ 0.24.0 (2018-04-04)::
* Added support for hmac-ripemd160
* Fixed https://github.com/hierynomus/sshj/issues/382[#382]: Fixed escaping in WildcardHostmatcher
* Added integration testsuite using Docker against OpenSSH
* Fixed https://github.com/hierynomus/sshj/issues/187[#187]: Fixed length bug in Buffer.putString
* Fixed https://github.com/hierynomus/sshj/issues/405[#405]: Continue host verification if first hostkey does not match.
SSHJ 0.23.0 (2017-10-13)::
* Merged https://github.com/hierynomus/sshj/pulls/372[#372]: Upgrade to 'net.i2p.crypto:eddsa:0.2.0'
* Fixed https://github.com/hierynomus/sshj/issues/355[#355] and https://github.com/hierynomus/sshj/issues/354[#354]: Correctly decode signature bytes
* Fixed https://github.com/hierynomus/sshj/issues/365[#365]: Added support for new-style OpenSSH fingerprints of server keys
* Fixed https://github.com/hierynomus/sshj/issues/356[#356]: Fixed key type detection for ECDSA public keys
* Made SSHJ Java9 compatible
SSHJ 0.22.0 (2017-08-24)::
* Fixed https://github.com/hierynomus/sshj/pulls/341[#341]: Fixed path walking during recursive copy
* Merged https://github.com/hierynomus/sshj/pulls/338[#338]: Added ConsolePasswordFinder to read password from stdin
* Merged https://github.com/hierynomus/sshj/pulls/336[#336]: Added support for ecdsa-sha2-nistp384 and ecdsa-sha2-nistp521 signatures
* Fixed https://github.com/hierynomus/sshj/issues/331[#331]: Added support for wildcards in known_hosts file
SSHJ 0.21.1 (2017-04-25)::
* Merged https://github.com/hierynomus/sshj/pulls/322[#322]: Fix regression from 40f956b (invalid length parameter on outputstream)
SSHJ 0.21.0 (2017-04-14)::
* Merged https://github.com/hierynomus/sshj/pulls/319[#319]: Added support for `ssh-rsa-cert-v01@openssh.com` and `ssh-dsa-cert-v01@openssh.com` certificate key files
* Upgraded Gradle to 3.4.1
* Merged https://github.com/hierynomus/sshj/pulls/305[#305]: Added support for custom string encoding
* Fixed https://github.com/hierynomus/sshj/issues/312[#312]: Upgraded BouncyCastle to 1.56
SSHJ 0.20.0 (2017-02-09)::
* Merged https://github.com/hierynomus/sshj/pulls/294[#294]: Reference ED25519 by constant instead of name
* Merged https://github.com/hierynomus/sshj/pulls/293[#293], https://github.com/hierynomus/sshj/pulls/295[#295] and https://github.com/hierynomus/sshj/pulls/301[#301]: Fixed OSGi packaging
* Added new Diffie Hellman groups 15-18 for stronger KeyExchange algorithms
SSHJ 0.19.1 (2016-12-30)::
* Enabled PKCS5 Key files in DefaultConfig
* Merged https://github.com/hierynomus/sshj/pulls/291[#291]: Fixed sshj.properties loading and chained exception messages
* Merged https://github.com/hierynomus/sshj/pulls/284[#284]: Correctly catch interrupt in keepalive thread
* Fixed https://github.com/hierynomus/sshj/issues/292[#292]: Pass the configured RandomFactory to Diffie Hellman KEX
* Fixed https://github.com/hierynomus/sshj/issues/256[#256]: SSHJ now builds if no git repository present
* LocalPortForwarder now correctly interrupts its own thread on close()
SSHJ 0.19.0 (2016-11-25)::
* Fixed https://github.com/hierynomus/sshj/issues/276[#276]: Add support for ed-25519 and new OpenSSH key format
* Fixed https://github.com/hierynomus/sshj/issues/280[#280]: Read version from a generated sshj.properties file to correctly output version during negotiation
SSHJ 0.18.0 (2016-09-30)::
* Fixed Android compatibility
* Upgrade to Gradle 3.0
* Merged https://github.com/hierynomus/sshj/pulls/271[#271]: Load known_hosts without requiring BouncyCastle
* Merged https://github.com/hierynomus/sshj/pulls/269[#269]: Brought back Java6 support by popular demand
* Merged https://github.com/hierynomus/sshj/pulls/267[#267]: Added support for per connection logging (Fixes https://github.com/hierynomus/sshj/issues/264[#264])
* Merged https://github.com/hierynomus/sshj/pulls/262[#262], https://github.com/hierynomus/sshj/pulls/265[#265] and https://github.com/hierynomus/sshj/pulls/266[#266]: Added PKCS5 key file support
* Fixed toString of sftp FileAttributes (Fixes https://github.com/hierynomus/sshj/pulls/258[#258])
* Fixed https://github.com/hierynomus/sshj/issues/255[#255]: No longer depending on 'privately marked' classes in `net.i2p.crypto.eddsa.math` package, fixes OSGI dependencies
SSHJ 0.17.2 (2016-07-07)::
* Treating SSH Server identification line ending in '\n' instead of '\r\n' leniently.
SSHJ 0.17.1 (2016-07-06)::
* Improved parsing of the SSH Server identification. Too long header lines now no longer break the protocol.
SSHJ 0.17.0 (2016-07-05)::
* *Introduced breaking change in SFTP copy behaviour*: Previously an SFTP copy operation would behave differently if both source and target were folders with different names.
In this case instead of copying the contents of the source into the target directory, the directory itself was copied as a sub directory of the target directory.
This behaviour has been removed in favour of the default behaviour which is to copy the contents of the source into the target. Bringing the behaviour in line with how SCP works.
* Fixed https://github.com/hierynomus/sshj/issues/252[#252] (via: https://github.com/hierynomus/sshj/pulls/253[#253]): Same name subdirs are no longer merged by accident
SSHJ 0.16.0 (2016-04-11)::
* Fixed https://github.com/hierynomus/sshj/issues/239[#239]: Remote port forwards did not work if you used the empty string as address, or a catch-all address.
* Fixed https://github.com/hierynomus/sshj/issues/242[#242]: Added OSGI headers to sources jar manifest
* Fixed https://github.com/hierynomus/sshj/issues/236[#236]: Remote Port forwarding with dynamic port allocation fails with BufferUnderflowException
* Upgraded gradle distribution to 2.12
* Closed https://github.com/hierynomus/sshj/issues/234[#234]: Dropped Java6 support (0.15.0 was already Java6 incompatible due to Java7 dependency)
* Fixed https://github.com/hierynomus/sshj/issues/118[#118]: Added configuration switch for waiting on a server ident before sending the client ident.
* Fixed https://github.com/hierynomus/sshj/issues/114[#114]: Added javadoc that you always need to call close() on a Command before inspecting the exit codes.
* Fixed https://github.com/hierynomus/sshj/issues/237[#237]: Fixed race condition if a `hostkeys-00@openssh.com` global request is received directly after a successful auth.
SSHJ 0.15.0 (2015-11-20)::
* Fixed https://github.com/hierynomus/sshj/issues/220[#220]: Added support for `ssh-ed25519` host keys
* Fixed https://github.com/hierynomus/sshj/issues/225[#225]: Fixed bug in ECDSA fingerprint calculation that sometimes produced an incorrect fingerprint
* Added `arcfour` Stream Ciphers from RFC4253 and RFC4345
* Added all Block Ciphers from RFC4344 and RFC4253
SSHJ 0.14.0 (2015-11-04)::
* Fixed https://github.com/hierynomus/sshj/issues/171[#171]: Added support for `curve25519-sha256@libssh.org` key exchange algorithm
* Added support for `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384` and `ecdh-sha2-nistp521` key exchange algorithms
* Fixed https://github.com/hierynomus/sshj/issues/167[#167]: Added support for `diffie-hellman-group-exchange-sha1` and `diffie-hellman-group-exchange-sha256` key exchange methods
* Fixed https://github.com/hierynomus/sshj/issues/212[#212]: Configure path escaping to enable shell expansion to work correctly
* Merged https://github.com/hierynomus/sshj/issues/210[#210]: RemoteFileInputStream.skip returns wrong value (Fixes https://github.com/hierynomus/sshj/issues/209[#209])
* Merged https://github.com/hierynomus/sshj/issues/208[#208]: Added SCP bandwidth limitation support
* Merged https://github.com/hierynomus/sshj/issues/211[#211]: Made keyfile format detection more robust
SSHJ 0.13.0 (2015-08-18)::
* Merged https://github.com/hierynomus/sshj/issues/199[#199]: Fix for IndexOutOfBoundsException in ReadAheadRemoteFileInputStream, fixes https://github.com/hierynomus/sshj/issues/183[#183]
* Merged https://github.com/hierynomus/sshj/issues/195[#195]: New authentication supported: `gssapi-with-mic`
* Merged https://github.com/hierynomus/sshj/issues/201[#201]: New option to verify negotiated key exchange algorithms
* Merged https://github.com/hierynomus/sshj/issues/196[#196]: Fix for looking up complete hostname in known hosts file
SSHJ 0.12.0 (2015-04-14)::
* Added support for HTTP proxies when running JDK6 or JDK7, fixes: https://github.com/hierynomus/sshj/issues/170[#170]
* Merged https://github.com/hierynomus/sshj/issues/186[#186]: Fix for detecting end-of-stream
* Compiling to JDK6, fixes https://github.com/hierynomus/sshj/issues/179[#179] and https://github.com/hierynomus/sshj/issues/185[#185]
* Correctly close socket and channel when LocalPortForwarder fails to open and start the channel (Fixes https://github.com/hierynomus/sshj/issues/175[#175] and https://github.com/hierynomus/sshj/issues/176[#176])
* Merged https://github.com/hierynomus/sshj/issues/181[#181]: Invalid write packet length when reading with offset (Fixes https://github.com/hierynomus/sshj/issues/180[#180])
SSHJ 0.11.0 (2015-01-23)::
SSHJ 0.11.0 (No date set yet)::
* New maven coordinates `com.hierynomus:sshj:0.11.0` as https://github.com/hierynomus[@hierynomus] took over as maintainer of SSHJ
* Migrated build system to Gradle 2.2.1
* Merged https://github.com/hierynomus/sshj/issues/150[#150]: Fix for incorrect file handle on some SSH servers, fixes: https://github.com/hierynomus/sshj/issues/54[#54], https://github.com/hierynomus/sshj/issues/119[#119], https://github.com/hierynomus/sshj/issues/168[#168], https://github.com/hierynomus/sshj/issues/169[#169]

View File

@@ -1,167 +1,24 @@
import java.text.SimpleDateFormat
import com.bmuschko.gradle.docker.tasks.container.*
import com.bmuschko.gradle.docker.tasks.image.*
plugins {
id "java"
id "groovy"
id "jacoco"
id "com.github.blindpirate.osgi" version '0.0.3'
id "maven-publish"
id 'pl.allegro.tech.build.axion-release' version '1.11.0'
id "com.bmuschko.docker-remote-api" version "3.2.1"
id "com.github.hierynomus.license" version "0.12.1"
id "com.jfrog.bintray" version "1.7"
id 'ru.vyarus.java-lib' version '1.0.5'
// id 'ru.vyarus.pom' version '1.0.3'
id 'ru.vyarus.github-info' version '1.1.0'
id 'ru.vyarus.animalsniffer' version '1.5.0'
}
apply plugin: "java"
apply plugin: "maven"
apply plugin: "signing"
apply plugin: "osgi"
group = "com.hierynomus"
scmVersion {
tag {
prefix = 'v'
versionSeparator = ''
}
hooks {
pre 'fileUpdate', [file: 'README.adoc', pattern: { v, c -> /:sshj_version: .*/}, replacement: { v, c -> ":sshj_version: $v" }]
pre 'commit'
}
}
project.version = scmVersion.version
defaultTasks "build"
version = "0.11.0"
repositories {
mavenCentral()
}
sourceCompatibility = 1.7
targetCompatibility = 1.7
configurations.compile.transitive = false
def bouncycastleVersion = "1.65"
def sshdVersion = "2.1.0"
dependencies {
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
implementation "org.slf4j:slf4j-api:1.7.7"
implementation "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
implementation "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
implementation "com.jcraft:jzlib:1.1.3"
implementation "net.i2p.crypto:eddsa:0.3.0"
testImplementation "junit:junit:4.12"
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.4'
testImplementation "org.mockito:mockito-core:2.28.2"
testImplementation "org.apache.sshd:sshd-core:$sshdVersion"
testImplementation "org.apache.sshd:sshd-sftp:$sshdVersion"
testImplementation "org.apache.sshd:sshd-scp:$sshdVersion"
testRuntimeOnly "ch.qos.logback:logback-classic:1.2.3"
testImplementation 'org.glassfish.grizzly:grizzly-http-server:2.4.4'
testImplementation 'org.apache.httpcomponents:httpclient:4.5.9'
}
license {
header rootProject.file('LICENSE_HEADER')
strictCheck true
mapping {
java = 'SLASHSTAR_STYLE'
}
excludes(['**/djb/Curve25519.java', '**/sshj/common/Base64.java', '**/org/mindrot/jbcrypt/*.java'])
}
// This disables the pedantic doclint feature of JDK8
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
task writeSshjVersionProperties {
doLast {
project.file("${project.buildDir}/resources/main").mkdirs()
project.file("${project.buildDir}/resources/main/sshj.properties").withWriter { w ->
w.append("sshj.version=${version}")
}
}
}
jar.dependsOn writeSshjVersionProperties
jar {
manifest {
// please see http://bnd.bndtools.org/chapters/390-wrapping.html
instruction "Bundle-Description", "SSHv2 library for Java"
instruction "Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt"
instruction "Import-Package", "!net.schmizz.*"
instruction "Import-Package", "!com.hierynomus.sshj.*"
instruction "Import-Package", "javax.crypto*"
instruction "Import-Package", "!net.i2p.crypto.eddsa.math"
instruction "Import-Package", "net.i2p*"
instruction "Import-Package", "com.jcraft.jzlib*;version=\"[1.1,2)\";resolution:=optional"
instruction "Import-Package", "org.slf4j*;version=\"[1.7,5)\""
instruction "Import-Package", "org.bouncycastle*;resolution:=optional"
instruction "Import-Package", "org.bouncycastle.jce.provider;resolution:=optional"
instruction "Import-Package", "*"
instruction "Export-Package", "com.hierynomus.sshj.*;version=\"${project.jar.manifest.version}\""
instruction "Export-Package", "net.schmizz.*;version=\"${project.jar.manifest.version}\""
}
}
sourcesJar {
manifest {
attributes(
// Add the needed OSGI attributes
"Bundle-ManifestVersion": "2",
"Bundle-Name": "${project.jar.manifest.name} Source",
"Bundle-Version": project.jar.manifest.version,
"Eclipse-SourceBundle": "${project.jar.manifest.symbolicName};version=\"${project.jar.manifest.version}\";roots:=\".\"",
"Bundle-SymbolicName": "${project.jar.manifest.symbolicName}.source"
)
}
mavenLocal()
}
configurations {
integrationTestImplementation.extendsFrom testImplementation
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
}
sourceSets {
integrationTest {
groovy {
compileClasspath += sourceSets.main.output + sourceSets.test.output
runtimeClasspath += sourceSets.main.output + sourceSets.test.output
srcDir file('src/itest/groovy')
}
resources.srcDir file('src/itest/resources')
compile {
transitive = false
}
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
tasks.withType(Test) {
testLogging {
exceptionFormat = 'full'
}
test {
include "**/*Test.*"
include "**/*Spec.*"
if (!project.hasProperty("allTests")) {
useJUnit {
excludeCategories 'com.hierynomus.sshj.test.SlowTests'
excludeCategories 'com.hierynomus.sshj.test.KnownFailingTests'
}
}
afterSuite { descriptor, result ->
if (descriptor.className != null) {
def indicator = "\u001B[32m✓\u001b[0m"
@@ -173,117 +30,129 @@ tasks.withType(Test) {
}
}
project.tasks.compileGroovy.onlyIf { false }
def bouncycastleVersion = "1.51"
github {
user 'hierynomus'
license 'Apache'
dependencies {
compile "org.slf4j:slf4j-api:1.7.7"
compile "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
compile "com.jcraft:jzlib:1.1.3"
testCompile "junit:junit:4.11"
testCompile "org.mockito:mockito-core:1.9.5"
testCompile "org.apache.sshd:sshd-core:0.11.0"
testRuntime "ch.qos.logback:logback-classic:1.1.2"
}
pom {
description "SSHv2 library for Java"
url "https://github.com/hierynomus/sshj"
inceptionYear "2009"
developers {
developer {
id "hierynomus"
name "Jeroen van Erp"
email "jeroen@javadude.nl"
roles {
role "Lead developer"
}
}
developer {
id "shikhar"
name "Shikhar Bhushan"
email "shikhar@schmizz.net"
url "http://schmizz.net"
roles {
role "Previous lead developer"
}
}
developer {
id "iterate"
name "David Kocher"
email "dkocher@iterate.ch"
organization "iterage GmbH"
organizationUrl "https://iterate.ch"
roles {
role "Developer"
}
}
jar {
manifest {
instruction "Bundle-Description", "SSHv2 library for Java"
instruction "Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt"
instruction "Import-Package", "!net.schmizz.*"
instruction "Import-Package", "javax.crypto*"
instruction "Import-Package", "com.jcraft.jzlib*;version=\"[1.1,2)\";resolution:=optional"
instruction "Import-Package", "org.slf4j*;version=\"[1.7,5)\""
instruction "Import-Package", "org.bouncycastle*"
instruction "Import-Package", "*"
instruction "Export-Package", "net.schmizz.*"
}
}
if (project.hasProperty("bintrayUsername") && project.hasProperty("bintrayApiKey")) {
bintray {
user = project.property("bintrayUsername")
key = project.property("bintrayApiKey")
publish = true
publications = ["maven"]
pkg {
repo = "maven"
name = project.name
licenses = ["Apache-2.0"]
vcsUrl = "https://github.com/hierynomus/sshj.git"
labels = ["ssh", "sftp", "secure-shell", "network", "file-transfer"]
githubRepo = "hierynomus/sshj"
version {
name = "${project.version}"
vcsTag = "v${project.version}"
released = new SimpleDateFormat('yyyy-MM-dd\'T\'HH:mm:ss.SSSZZ').format(new Date())
gpg {
sign = true
passphrase = project.property("signing.password")
task javadocJar(type: Jar) {
classifier = 'javadoc'
from javadoc
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives javadocJar, sourcesJar
}
signing {
required { !version.contains("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
// This disables the pedantic doclint feature of JDK8
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
uploadArchives {
if(project.hasProperty('sonatypeUsername')) {
repositories.mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
configuration = configurations.archives
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
pom.project {
name "sshj"
description "SSHv2 library for Java"
url "https://github.com/hierynomus/sshj"
inceptionYear "2009"
issueManagement {
system "github"
url "https://github.com/hierynomus/sshj/issues"
}
mavenCentralSync {
sync = true
user = project.property("sonatypeUsername")
password = project.property("sonatypePassword")
close = 1
scm {
connection "scm:git:git://github.com/hierynomus/sshj.git"
developerConnection "scm:git:git@github.com:hierynomus/sshj.git"
url "https://github.com/hierynomus/sshj.git"
}
licenses {
license {
name "Apache 2"
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
}
}
developers {
developer {
id "hierynomus"
name "Jeroen van Erp"
email "jeroen@javadude.nl"
roles {
role "Lead developer"
}
}
developer {
id "shikhar"
name "Shikhar Bhushan"
email "shikhar@schmizz.net"
url "http://schmizz.net"
roles {
role "Previous lead developer"
}
}
developer {
id "iterate"
name "David Kocher"
email "dkocher@iterate.ch"
organization "iterage GmbH"
organizationUrl "https://iterate.ch"
roles {
role "Developer"
}
}
}
}
}
}
}
jacocoTestReport {
reports {
xml.enabled true
html.enabled true
}
}
task buildItestImage(type: DockerBuildImage) {
inputDir = file('src/itest/docker-image')
tag = 'sshj/sshd-itest'
}
task createItestContainer(type: DockerCreateContainer) {
dependsOn buildItestImage
targetImageId { buildItestImage.getImageId() }
portBindings = ['2222:22']
}
task startItestContainer(type: DockerStartContainer) {
dependsOn createItestContainer
targetContainerId { createItestContainer.getContainerId() }
}
task stopItestContainer(type: DockerStopContainer) {
targetContainerId { createItestContainer.getContainerId() }
}
task forkedUploadRelease(type: GradleBuild) {
buildFile = project.buildFile
tasks = ["bintrayUpload"]
}
project.tasks.integrationTest.dependsOn(startItestContainer)
project.tasks.integrationTest.finalizedBy(stopItestContainer)
project.tasks.release.dependsOn([project.tasks.integrationTest, project.tasks.build])
project.tasks.release.finalizedBy(project.tasks.forkedUploadRelease)
project.tasks.jacocoTestReport.dependsOn(project.tasks.test)
project.tasks.check.dependsOn(project.tasks.jacocoTestReport)

View File

@@ -21,10 +21,10 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.hierynomus</groupId>
<artifactId>sshj-examples</artifactId>
<groupId>net.schmizz</groupId>
<artifactId>sshj</artifactId>
<packaging>jar</packaging>
<version>0.19.1</version>
<version>0.10.0</version>
<name>sshj-examples</name>
<description>Examples for SSHv2 library for Java</description>
@@ -53,9 +53,9 @@
<dependencies>
<dependency>
<groupId>com.hierynomus</groupId>
<groupId>net.schmizz</groupId>
<artifactId>sshj</artifactId>
<version>0.24.0</version>
<version>0.10.0</version>
</dependency>
</dependencies>

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -5,36 +20,30 @@ import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import java.io.Console;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/** This examples demonstrates how a remote command can be executed. */
public class Exec {
private static final Console con = System.console();
public static void main(String... args)
throws IOException {
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
ssh.connect("localhost");
Session session = null;
try {
ssh.authPublickey(System.getProperty("user.name"));
session = ssh.startSession();
final Command cmd = session.exec("ping -c 1 google.com");
con.writer().print(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
con.writer().print("\n** exit status: " + cmd.getExitStatus());
} finally {
final Session session = ssh.startSession();
try {
if (session != null) {
session.close();
}
} catch (IOException e) {
// Do Nothing
final Command cmd = session.exec("ping -c 1 google.com");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
System.out.println("\n** exit status: " + cmd.getExitStatus());
} finally {
session.close();
}
} finally {
ssh.disconnect();
}
}

View File

@@ -1,71 +0,0 @@
package net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts;
import net.schmizz.sshj.xfer.FileSystemFile;
import java.io.*;
import java.nio.charset.Charset;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
/** This examples demonstrates how to configure {@link net.schmizz.sshj.SSHClient} client with an in-memory known_hosts file */
public class InMemoryKnownHosts {
public static void main(String[] args) throws IOException {
InputStream entry = new ByteArrayInputStream("localhost ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPmhSBtMctNa4hsZt8QGlsYSE5/gMkjeand69Vj4ir13".getBytes(Charset.defaultCharset()));
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new InMemoryHostKeyVerifier(entry, Charset.defaultCharset()));
ssh.connect("localhost");
try {
ssh.authPublickey(System.getProperty("user.name"));
ssh.newSCPFileTransfer().download("test_file", new FileSystemFile("/tmp/"));
} finally {
ssh.disconnect();
}
}
public static class InMemoryHostKeyVerifier implements HostKeyVerifier {
private final List<OpenSSHKnownHosts.KnownHostEntry> entries = new ArrayList<OpenSSHKnownHosts.KnownHostEntry>();
public InMemoryHostKeyVerifier(InputStream inputStream, Charset charset) throws IOException {
final OpenSSHKnownHosts.EntryFactory entryFactory = new OpenSSHKnownHosts.EntryFactory();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset));
while(reader.ready()) {
String line = reader.readLine();
try {
OpenSSHKnownHosts.KnownHostEntry entry = entryFactory.parseEntry(line);
if (entry != null) {
entries.add(entry);
}
} catch (Exception e) {
//log error
}
}
}
@Override
public boolean verify(String hostname, int port, PublicKey key) {
final KeyType type = KeyType.fromKey(key);
if (type == KeyType.UNKNOWN) {
return false;
}
for (OpenSSHKnownHosts.KnownHostEntry e : entries) {
try {
if (e.appliesTo(type, hostname) && e.verify(key)) {
return true;
}
} catch (IOException ioe) {
//log error
}
}
return false;
}
}
}

View File

@@ -1,50 +0,0 @@
package net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.DirectConnection;
import net.schmizz.sshj.connection.channel.direct.Session;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* This example demonstrates connecting via an intermediate "jump" server using a direct TCP/IP channel.
*/
public class Jump {
public static void main(String... args)
throws IOException {
SSHClient firstHop = new SSHClient();
firstHop.loadKnownHosts();
firstHop.connect("localhost");
try {
firstHop.authPublickey(System.getProperty("user.name"));
DirectConnection tunnel = firstHop.newDirectConnection("localhost", 22);
SSHClient ssh = new SSHClient();
try {
ssh.loadKnownHosts();
ssh.connectVia(tunnel);
ssh.authPublickey(System.getProperty("user.name"));
final Session session = ssh.startSession();
try {
final Session.Command cmd = session.exec("ping -c 1 google.com");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
System.out.println("\n** exit status: " + cmd.getExitStatus());
} finally {
session.close();
}
} finally {
ssh.disconnect();
}
} finally {
firstHop.disconnect();
}
}
}

View File

@@ -1,13 +1,31 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.DefaultConfig;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/** This examples demonstrates how to setup keep-alive to detect connection dropping. */
public class KeepAlive {

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -9,7 +24,6 @@ import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts;
import java.io.File;
import java.io.IOException;
import net.schmizz.sshj.common.LoggerFactory;
/** A very rudimentary psuedo-terminal based on console I/O. */
class RudimentaryPTY {
@@ -34,18 +48,18 @@ class RudimentaryPTY {
final Shell shell = session.startShell();
new StreamCopier(shell.getInputStream(), System.out, LoggerFactory.DEFAULT)
new StreamCopier(shell.getInputStream(), System.out)
.bufSize(shell.getLocalMaxPacketSize())
.spawn("stdout");
new StreamCopier(shell.getErrorStream(), System.err, LoggerFactory.DEFAULT)
new StreamCopier(shell.getErrorStream(), System.err)
.bufSize(shell.getLocalMaxPacketSize())
.spawn("stderr");
// Now make System.in act as stdin. To exit, hit Ctrl+D (since that results in an EOF on System.in)
// This is kinda messy because java only allows console input after you hit return
// But this is just an example... a GUI app could implement a proper PTY
new StreamCopier(System.in, shell.getOutputStream(), LoggerFactory.DEFAULT)
new StreamCopier(System.in, shell.getOutputStream())
.bufSize(shell.getRemoteMaxPacketSize())
.copy();

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -22,4 +37,4 @@ public class SCPDownload {
}
}
}
}

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -27,4 +42,4 @@ public class SCPUpload {
ssh.disconnect();
}
}
}
}

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -27,4 +42,4 @@ public class SFTPDownload {
}
}
}
}

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -29,4 +44,4 @@ public class SFTPUpload {
}
}
}
}

View File

@@ -1,3 +1,18 @@
/**
* Copyright 2009 sshj contributors
*
* Licensed 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 net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
@@ -5,7 +20,6 @@ import net.schmizz.sshj.common.StreamCopier;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.connection.channel.forwarded.SocketForwardingConnectListener;
import net.schmizz.sshj.common.LoggerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -43,8 +57,8 @@ public class X11 {
final Command cmd = sess.exec("/usr/X11/bin/xcalc");
new StreamCopier(cmd.getInputStream(), System.out, LoggerFactory.DEFAULT).spawn("stdout");
new StreamCopier(cmd.getErrorStream(), System.err, LoggerFactory.DEFAULT).spawn("stderr");
new StreamCopier(cmd.getInputStream(), System.out).spawn("stdout");
new StreamCopier(cmd.getErrorStream(), System.err).spawn("stderr");
// Wait for session & X11 channel to get closed
ssh.getConnection().join();
@@ -53,4 +67,4 @@ public class X11 {
ssh.disconnect();
}
}
}
}

Binary file not shown.

View File

@@ -1,6 +1,6 @@
#Wed Jan 21 09:17:25 CET 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip

110
gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
##############################################################################
##
@@ -6,6 +6,47 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -20,49 +61,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -89,7 +90,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -113,7 +114,6 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,19 +154,11 @@ if $cygwin ; then
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
APP_ARGS=$(save "$@")
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

14
gradlew.bat vendored
View File

@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,9 +46,10 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -59,6 +60,11 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

344
pom.xml Normal file
View File

@@ -0,0 +1,344 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2009 sshj contributors
Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.schmizz</groupId>
<artifactId>sshj</artifactId>
<packaging>bundle</packaging>
<version>0.10.1-SNAPSHOT</version>
<name>sshj</name>
<description>SSHv2 library for Java</description>
<url>http://github.com/hierynomus/sshj</url>
<inceptionYear>2009</inceptionYear>
<issueManagement>
<system>github</system>
<url>http://github.com/hierynomus/sshj/issues</url>
</issueManagement>
<scm>
<connection>scm:git:git://github.com/hierynomus/sshj.git</connection>
<developerConnection>scm:git:git@github.com:hierynomus/sshj.git</developerConnection>
<url>http://github.com/hierynomus/sshj</url>
</scm>
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.51</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.51</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jzlib</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jzlib</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>0.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<developers>
<developer>
<id>hierynomus</id>
<name>Jeroen van Erp</name>
<email>jeroen@hierynomus.com</email>
</developer>
<developer>
<id>shikhar</id>
<name>Shikhar Bhushan</name>
<email>shikhar@schmizz.net</email>
<url>http://schmizz.net</url>
</developer>
<developer>
<id>iterate</id>
<name>David Kocher</name>
<email>dkocher@iterate.ch</email>
<organization>iterate GmbH</organization>
<organizationUrl>https://iterate.ch</organizationUrl>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>
!net.schmizz.*,
javax.crypto*,
com.jcraft.jzlib*;version="[1.1,2)";resolution:=optional,
org.slf4j*;version="[1.7,5)",
org.bouncycastle*,
*
</Import-Package>
<Export-Package>net.schmizz.*</Export-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>clirr-maven-plugin</artifactId>
<version>2.6.1</version>
</plugin>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.6</version>
<configuration>
<header>src/etc/license-header</header>
<properties>
<owner>sshj contributors</owner>
<email>sshj-users@googlegroups.com</email>
</properties>
<excludes>
<exclude>**/README</exclude>
<exclude>src/test/resources/**</exclude>
<exclude>src/main/resources/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.2</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
--> </plugins>
</build>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<profiles>
<profile>
<id>full-deps</id>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jzlib</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>doclint-java8-disable</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>clirr-maven-plugin</artifactId>
<version>2.6.1</version>
</plugin>
</plugins>
</reporting>
</project>

View File

@@ -1 +0,0 @@
rootProject.name = "sshj"

View File

@@ -1,23 +0,0 @@
FROM sickp/alpine-sshd:7.5-r2
ADD authorized_keys /home/sshj/.ssh/authorized_keys
ADD test-container/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key
ADD test-container/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key.pub
ADD test-container/ssh_host_ed25519_key /etc/ssh/ssh_host_ed25519_key
ADD test-container/ssh_host_ed25519_key.pub /etc/ssh/ssh_host_ed25519_key.pub
ADD test-container/sshd_config /etc/ssh/sshd_config
RUN apk add --no-cache tini
RUN \
echo "root:smile" | chpasswd && \
adduser -D -s /bin/ash sshj && \
passwd -u sshj && \
chmod 600 /home/sshj/.ssh/authorized_keys && \
chmod 600 /etc/ssh/ssh_host_ecdsa_key && \
chmod 644 /etc/ssh/ssh_host_ecdsa_key.pub && \
chmod 600 /etc/ssh/ssh_host_ed25519_key && \
chmod 644 /etc/ssh/ssh_host_ed25519_key.pub && \
chown -R sshj:sshj /home/sshj
ENTRYPOINT ["/sbin/tini", "/entrypoint.sh"]

View File

@@ -1,7 +0,0 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOEQcvowiV3igdRO7rKPrZrao1hCQrnC4tgsxqSJdQCbABI+vHrdbJRfWZNuSk48aAtARJzJVmkn/r63EPJgkh8= root@itgcpkerberosstack-cbgateway-0-20151117031915
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHQiZm0wBbmI8gohA/N9ir1O+egikL6S9FjZS8GHbx4rTHI1V+vbXxx2O9bFWtep1PFb4iowtZkxf6gvRjGkL6M= ajvanerp@Heimdall.local
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDAdJiRkkBM8yC8seTEoAn2PfwbLKrkcahZ0xxPoWICJ root@sshj
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8ww4hJG/gHJYdkjTTBDF1GNz+228nuWprPV+NbQauA ajvanerp@Heimdall.local
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOaWrwt3drIOjeBq2LSHRavxAT7ja2f+5soOUJl/zKSI ajvanerp@Heimdall.xebialabs.com
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoZ9l6Tkm2aL1tSBy2yw4xU5s8BE9MfqS/4J7DzvsYJxF6oQmTIjmStuhH/CT7UjuDtKXdXZUsIhKtafiizxGO8kHSzKDeitpth2RSr8ddMzZKyD6RNs7MfsgjA3UTtrrSrCXEY6O43S2cnuJrWzkPxtwxaQ3zOvDbS2tiulzyq0VzYmuhA/a4CyuQtJBuu+P2oqmu6pU/VB6IzONpvBvYbNPsH1WDmP7zko5wHPihXPCliztspKxS4DRtOZ7BGXyvg44UmIy0Kf4jOkaBV/eCCA4qH7ZHz71/5ceMOpszPcNOEmLGGYhwI+P3OuGMpkrSAv1f8IY6R8spZNncP6UaQ== no-passphrase
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDKRyZAtOJJfAhPU6xE6ZXY564vwErAI3n3Yn4lTHL9bxev9Ily6eCqPLcV0WbSV04pztngFn9MjT7yb8mcXheHpIaWEH569sMpmpOtyfn4p68SceuXBGyyPGMIcfOTknkASd1JYSD4EPkd9rZmCzcx3vEnLu8ChnA/G221xSVQ5VC/jD/c/CgNUayhQ+xbn57qHKKtZwfTa21QmwIabGYJNwlVjlKTCdddeVnZfKqKrG7cxHQApsxd21rhM9IT/C/f4Y/Tx3WUUVeam0iZ265oiPHoPALqJIWSQIUheRYAxYAQqJwSQ0Or9MM8XXun2Iy3RUSGk6eIvrCsFbNURsHNs7Pu0UnpYv6FZ3vCkFep/1pAT6fQvY7pDOOWDHKXArD4watc9gIWaQBH73wDW/KgBcnMRSoGWgQjsYqIamP4oV1+HqUI3lRAsXZaX+eiBGt3+3A5KebP27UJ1YUwhwlzs7wzTKaCu0OaL+hOsP1F2AxAa995bgFksMd23645ux3YCJKXG4sGpJ1Z/Hs49K72gv+QjLZVxXqY623c8+3OUhlixqoEFd4iG7UMc5a552ch/VA+jaspmLZoFhPz99aBRVb1oCSPxSwLw+Q/wxv6pZmT+14rqTzY2farjU53hM+CsUPh7dnWXhGG7RuA5wCdeOXOYjuksfzAoHIZhPqTgQ== ajvanerp@Heimdall.local

View File

@@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOpOBFjqe0hjK/hs4WZ3dZqnzanq1L3/JbvV1TCkbe4ToAoGCCqGSM49
AwEHoUQDQgAEVzkrS7Yj0nXML7A3mE08YDthfBR/ZbyYJDIq1vTzcqs6KTaCT529
swNXWLHO+mbHviZcRiI57ULXHZ1emom/Jw==
-----END EC PRIVATE KEY-----

View File

@@ -1 +0,0 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFc5K0u2I9J1zC+wN5hNPGA7YXwUf2W8mCQyKtb083KrOik2gk+dvbMDV1ixzvpmx74mXEYiOe1C1x2dXpqJvyc= root@404b27be2bf4

View File

@@ -1,7 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBFG9PKAq8FtH0me+LHUE6YaVANCMqy/Znkffzief1W/gAAAKCyyoBkssqA
ZAAAAAtzc2gtZWQyNTUxOQAAACBFG9PKAq8FtH0me+LHUE6YaVANCMqy/Znkffzief1W/g
AAAED+Yfza2xk5LqP9pN6TpvhWYP0L60zOQJpHhbEuiS3LLkUb08oCrwW0fSZ74sdQTphp
UA0IyrL9meR9/OJ5/Vb+AAAAF2FqdmFuZXJwQEhlaW1kYWxsLmxvY2FsAQIDBAUG
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEUb08oCrwW0fSZ74sdQTphpUA0IyrL9meR9/OJ5/Vb+ ajvanerp@Heimdall.local

View File

@@ -1,132 +0,0 @@
# $OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/bin:/usr/bin:/sbin:/usr/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem sftp /usr/lib/ssh/sftp-server
# the following are HPN related configuration options
# tcp receive buffer polling. disable in non autotuning kernels
#TcpRcvBufPoll yes
# disable hpn performance boosts
#HPNDisabled no
# buffer size for hpn to non-hpn connections
#HPNBufferSize 2048
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1
macs umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com

View File

@@ -1,42 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj
import net.schmizz.sshj.Config
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.SSHClient
import net.schmizz.sshj.transport.verification.PromiscuousVerifier
import spock.lang.Specification
class IntegrationBaseSpec extends Specification {
protected static final int DOCKER_PORT = 2222
protected static final String USERNAME = "sshj"
protected static final String KEYFILE = "src/itest/resources/keyfiles/id_rsa"
protected final static String SERVER_IP = System.getProperty("serverIP", "127.0.0.1")
protected static SSHClient getConnectedClient(Config config) {
SSHClient sshClient = new SSHClient(config)
sshClient.addHostKeyVerifier(new PromiscuousVerifier())
sshClient.connect(SERVER_IP, DOCKER_PORT)
return sshClient
}
protected static SSHClient getConnectedClient() throws IOException {
return getConnectedClient(new DefaultConfig())
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj
import com.hierynomus.sshj.signature.SignatureEdDSA
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.SSHClient
import net.schmizz.sshj.signature.SignatureECDSA
import net.schmizz.sshj.transport.TransportException
import net.schmizz.sshj.userauth.UserAuthException
import spock.lang.Unroll
class IntegrationSpec extends IntegrationBaseSpec {
@Unroll
def "should accept correct key for #signatureName"() {
given:
def config = new DefaultConfig()
config.setSignatureFactories(signatureFactory)
SSHClient sshClient = new SSHClient(config)
sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint
when:
sshClient.connect(SERVER_IP, DOCKER_PORT)
then:
sshClient.isConnected()
where:
signatureFactory << [new SignatureECDSA.Factory256(), new SignatureEdDSA.Factory()]
fingerprint << ["d3:6a:a9:52:05:ab:b5:48:dd:73:60:18:0c:3a:f0:a3", "dc:68:38:ce:fc:6f:2c:d6:6d:6b:34:eb:5c:f0:41:6a"]
signatureName = signatureFactory.getName()
}
def "should decline wrong key"() throws IOException {
given:
SSHClient sshClient = new SSHClient(new DefaultConfig())
sshClient.addHostKeyVerifier("d4:6a:a9:52:05:ab:b5:48:dd:73:60:18:0c:3a:f0:a3")
when:
sshClient.connect(SERVER_IP, DOCKER_PORT)
then:
thrown(TransportException.class)
}
@Unroll
def "should authenticate with key #key"() {
given:
SSHClient client = getConnectedClient()
when:
def keyProvider = passphrase != null ? client.loadKeys("src/itest/resources/keyfiles/$key", passphrase) : client.loadKeys("src/itest/resources/keyfiles/$key")
client.authPublickey(USERNAME, keyProvider)
then:
client.isAuthenticated()
where:
key | passphrase
// "id_ecdsa_nistp256" | null // TODO: Need to improve PKCS8 key support.
"id_ecdsa_opensshv1" | null
"id_ed25519_opensshv1" | null
"id_ed25519_opensshv1_aes256cbc.pem" | "foobar"
"id_ed25519_opensshv1_protected" | "sshjtest"
"id_rsa" | null
"id_rsa_opensshv1" | null
}
def "should not authenticate with wrong key"() {
given:
SSHClient client = getConnectedClient()
when:
client.authPublickey("sshj", "src/itest/resources/keyfiles/id_unknown_key")
then:
thrown(UserAuthException.class)
!client.isAuthenticated()
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.sftp
import com.hierynomus.sshj.IntegrationBaseSpec
import net.schmizz.sshj.SSHClient
import net.schmizz.sshj.sftp.OpenMode
import net.schmizz.sshj.sftp.RemoteFile
import net.schmizz.sshj.sftp.SFTPClient
import java.nio.charset.StandardCharsets
import static org.codehaus.groovy.runtime.IOGroovyMethods.withCloseable
class FileWriteSpec extends IntegrationBaseSpec {
def "should append to file (GH issue #390)"() {
given:
SSHClient client = getConnectedClient()
client.authPublickey("sshj", "src/test/resources/id_rsa")
SFTPClient sftp = client.newSFTPClient()
def file = "/home/sshj/test.txt"
def initialText = "This is the initial text.\n".getBytes(StandardCharsets.UTF_16)
def appendText = "And here's the appended text.\n".getBytes(StandardCharsets.UTF_16)
when:
withCloseable(sftp.open(file, EnumSet.of(OpenMode.WRITE, OpenMode.CREAT))) { RemoteFile initial ->
initial.write(0, initialText, 0, initialText.length)
}
then:
withCloseable(sftp.open(file, EnumSet.of(OpenMode.READ))) { RemoteFile read ->
def bytes = new byte[initialText.length]
read.read(0, bytes, 0, bytes.length)
bytes == initialText
}
when:
withCloseable(sftp.open(file, EnumSet.of(OpenMode.WRITE, OpenMode.APPEND))) { RemoteFile append ->
append.write(0, appendText, 0, appendText.length)
}
then:
withCloseable(sftp.open(file, EnumSet.of(OpenMode.READ))) { RemoteFile read ->
def bytes = new byte[initialText.length + appendText.length]
read.read(0, bytes, 0, bytes.length)
Arrays.copyOfRange(bytes, 0, initialText.length) == initialText
Arrays.copyOfRange(bytes, initialText.length, initialText.length + appendText.length) == appendText
}
cleanup:
sftp.close()
client.close()
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.kex
import com.hierynomus.sshj.IntegrationBaseSpec
import com.hierynomus.sshj.transport.mac.Macs
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.transport.kex.Curve25519DH
import net.schmizz.sshj.transport.kex.Curve25519SHA256
import net.schmizz.sshj.transport.kex.DH
import net.schmizz.sshj.transport.kex.DHGexSHA1
import net.schmizz.sshj.transport.kex.DHGexSHA256
import net.schmizz.sshj.transport.kex.ECDH
import net.schmizz.sshj.transport.kex.ECDHNistP
import spock.lang.Unroll
class KexSpec extends IntegrationBaseSpec {
@Unroll
def "should correctly connect with #kex Key Exchange"() {
given:
def cfg = new DefaultConfig()
cfg.setKeyExchangeFactories(kexFactory)
def client = getConnectedClient(cfg)
when:
client.authPublickey(USERNAME, KEYFILE)
then:
client.authenticated
where:
kexFactory << [DHGroups.Group1SHA1(),
DHGroups.Group14SHA1(),
DHGroups.Group14SHA256(),
DHGroups.Group16SHA512(),
DHGroups.Group18SHA512(),
new DHGexSHA1.Factory(),
new DHGexSHA256.Factory(),
new Curve25519SHA256.Factory(),
new Curve25519SHA256.FactoryLibSsh(),
new ECDHNistP.Factory256(),
new ECDHNistP.Factory384(),
new ECDHNistP.Factory521()]
kex = kexFactory.name
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.mac
import com.hierynomus.sshj.IntegrationBaseSpec
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.transport.mac.HMACRIPEMD160
import net.schmizz.sshj.transport.mac.HMACSHA2256
import spock.lang.AutoCleanup
import spock.lang.Unroll
class MacSpec extends IntegrationBaseSpec {
@Unroll
def "should correctly connect with #mac MAC"() {
given:
def cfg = new DefaultConfig()
cfg.setMACFactories(macFactory)
def client = getConnectedClient(cfg)
when:
client.authPublickey(USERNAME, KEYFILE)
then:
client.authenticated
cleanup:
client.disconnect()
where:
macFactory << [Macs.HMACRIPEMD160(), Macs.HMACRIPEMD160OpenSsh(), Macs.HMACSHA2256(), Macs.HMACSHA2512()]
mac = macFactory.name
}
@Unroll
def "should correctly connect with Encrypt-Then-Mac #mac MAC"() {
given:
def cfg = new DefaultConfig()
cfg.setMACFactories(macFactory)
def client = getConnectedClient(cfg)
when:
client.authPublickey(USERNAME, KEYFILE)
then:
client.authenticated
cleanup:
client.disconnect()
where:
macFactory << [Macs.HMACRIPEMD160Etm(), Macs.HMACSHA2256Etm(), Macs.HMACSHA2512Etm()]
mac = macFactory.name
}
}

View File

@@ -0,0 +1,39 @@
package nl.javadude.sshj.connection.channel;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.MatcherAssert.assertThat;
public class ChannelCloseEofTest {
private SSHClient sshClient;
@Before
public void setUp() throws Exception {
sshClient = new SSHClient();
}
@After
public void tearDown() throws IOException {
sshClient.disconnect();
}
@Test
public void shouldCorrectlyHandleSessionChannelEof() throws IOException, InterruptedException {
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
sshClient.connect("172.16.37.129");
sshClient.authPassword("jeroen", "jeroen");
Session session = sshClient.startSession();
session.allocateDefaultPTY();
session.close();
Thread.sleep(1000);
assertThat("Should still be connected", sshClient.isConnected());
}
}

View File

@@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJUMlsSlXqCZmCjlN4kV7hzP+p9pu0fwJ8r4m1qle58SoAoGCCqGSM49
AwEHoUQDQgAE4RBy+jCJXeKB1E7uso+tmtqjWEJCucLi2CzGpIl1AJsAEj68et1s
lF9Zk25KTjxoC0BEnMlWaSf+vrcQ8mCSHw==
-----END EC PRIVATE KEY-----

View File

@@ -1,9 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR0ImZtMAW5iPIKIQPzfYq9TvnoIpC+
kvRY2UvBh28eK0xyNVfr218cdjvWxVrXqdTxW+IqMLWZMX+oL0YxpC+jAAAAsD+6Oow/uj
qMAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHQiZm0wBbmI8goh
A/N9ir1O+egikL6S9FjZS8GHbx4rTHI1V+vbXxx2O9bFWtep1PFb4iowtZkxf6gvRjGkL6
MAAAAgXNC11pInVAOd3xNphiHMoISeitf6h1IKbDM+niLrL5kAAAAXYWp2YW5lcnBASGVp
bWRhbGwubG9jYWwB
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,7 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAwHSYkZJATPMgvLHkxKAJ9j38Gyyq5HGoWdMcT6FiAiQAAAJDimgR84poE
fAAAAAtzc2gtZWQyNTUxOQAAACAwHSYkZJATPMgvLHkxKAJ9j38Gyyq5HGoWdMcT6FiAiQ
AAAECmsckQycWnfGQK6XtQpaMGODbAkMQOdJNK6XJSipB7dDAdJiRkkBM8yC8seTEoAn2P
fwbLKrkcahZ0xxPoWICJAAAACXJvb3RAc3NoagECAwQ=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,8 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABBLQVXV9f
Wpw8AL9RTpAr//AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIJ8ww4hJG/gHJYdk
jTTBDF1GNz+228nuWprPV+NbQauAAAAAoGHEO7x3fSRBohvrIR52U4XD3uqRnhrPYm01k1
f4HHNNv46m92Zw6JKIB9Trrvp0sdMI8MVb79bN45rbn6mvpABtWl6T5TOTyMnKzDfAOx9c
FTaasWFmgtgkXOsu5pLrYBAQgCHWbzjjz6KoV1DmD4SAn9Ojf9Oh+YdAEKZcsvklgpu+Kj
nzN/DR0jt7Nzep2kNCLAS24QEkvQeATVSDiL8=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,8 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB/aWL0WG
iYPOTxGlFwvaCNAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOaWrwt3drIOjeBq
2LSHRavxAT7ja2f+5soOUJl/zKSIAAAAsKplAiFbOhzcOJYFYBYm8sqYbvhPF8jKdQFkbo
LAOeq+vQ0YBV9XUWQQM2tmL+RPjykPJZ2thcHLpVp3PfUEgo4bImCt939b3Ji3cEwD3QuK
MIhjhx1KvSJNF/uhjwPJnttwHG+ld8F5Gv7LpTOUmOzXKGLIgYRuwonhs5ezdNv5ERs+Cq
M9p/SW5ehL5KPJhGa5a+ZQXRojwEH7J4Q5xztH1gviTdIEpFWWQBH8rX6y
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEoAIBAAKCAQEAoZ9l6Tkm2aL1tSBy2yw4xU5s8BE9MfqS/4J7DzvsYJxF6oQm
TIjmStuhH/CT7UjuDtKXdXZUsIhKtafiizxGO8kHSzKDeitpth2RSr8ddMzZKyD6
RNs7MfsgjA3UTtrrSrCXEY6O43S2cnuJrWzkPxtwxaQ3zOvDbS2tiulzyq0VzYmu
hA/a4CyuQtJBuu+P2oqmu6pU/VB6IzONpvBvYbNPsH1WDmP7zko5wHPihXPClizt
spKxS4DRtOZ7BGXyvg44UmIy0Kf4jOkaBV/eCCA4qH7ZHz71/5ceMOpszPcNOEmL
GGYhwI+P3OuGMpkrSAv1f8IY6R8spZNncP6UaQIBIwKCAQBXvO4uJlbrLJQDPYAt
1i1ybGcF+rrR/Q34a2dgCpZDEwFiDTlcv1hxx689OXTf5cMPXGDZXX5udd9p7Wxa
NqnIrvVUtQWLdqcZuEeO+gitHr8IyMJf5Lm8C/u5vl1PYOYhO0qxwmrTP1u6fZPh
zWX2X1p5626/sy+TCisCRDeLRyes+Dtfs3bDjUq+zF3D/DmeYY55LUx0XS27uXNS
QuUDMSnymFyj4o+jPK0q/j5w4bB+0rbsij+EP7S//jOFrSEcZgBhhIj0rHA5fo6w
NrgtgRKD3HKFBM3b4VM8TdMbHsmf+nT9DjiDqcs+IxXMGlb1XTjtQFIN2eyRtNLd
eQ0bAoGBAMwgv3rGytRjVbR4TT77eF81svzitOJWRdfXuKB5gqM3jsPR08f1MEtZ
44kaI5ByJ3mBDt/EwNgLRdmBddPrLu3so9VLdRmWKI+KNGxwkcxzJv1xXdicgw+w
S5WgigJryuUbtdylXQTlRArLUKsXULk/MndhGiD+a4fZ3dUtktF9AoGBAMqxh6tr
S0ao0rN4hc9I92gwPubD1+XQr9TJQEEqGv3g5O3BdfDrTvizfaeNArahrIqyO5SK
7iDg0xcHqdxmVmmCJ8CkIWBPXLU6erQ1QNlBJmnzYn5lR0Ksx2h/myjeXztvJKEM
q4xUjAEzWjmwxxU3Y6l3FokvgIU4kOVoE4JdAoGARfyZa+xizHnUPeAae/5yaclE
rnmdGma43En2KGQsyj7vHpEVaSDdW6nKWuRj9wKRMPkMafpQvxnOzjsD06EXZ4RV
bbN4mw7pVcj8B+wUuyAqoAmchMfya8dqXy+6SfkSXS4Sd4knNODkIPVAOqjoegcJ
/QtZamXbuYyGkjuCy3sCgYBLSUEFJ9ohjymwX/cvvAQfYmCBmTLu9b2mzmhSt94j
yI+Lgl8BtnxrANbmdjQ1NLxuB6+61IRVWtIP3kZnzj1aY4sbqq1PqHLkOkrVOFnq
S2YKGJJMND8KIur67ZFm84J1KUgej61uow9uKQRBUEnx8AByJOsdAwPZteys+sVq
7wKBgAc3BL6ttDVYlL8U8fgvTCGuIajItvOQQj1n8RKyRLblYXBKAtY+pbULzmF+
HscRgJMcwEIosEbTzzBNEVQm6dS6R/Q534C00Fpsw1z/PFTI8AOdUzTROGjuN8Fg
YZoqMQLhk/PB8V4l7yJmPrE971RmJBBDlLDt6hZwOYEI2yF4
-----END RSA PRIVATE KEY-----

View File

@@ -1,49 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEAykcmQLTiSXwIT1OsROmV2OeuL8BKwCN592J+JUxy/W8Xr/SJcung
qjy3FdFm0ldOKc7Z4BZ/TI0+8m/JnF4Xh6SGlhB+evbDKZqTrcn5+KevEnHrlwRssjxjCH
Hzk5J5AEndSWEg+BD5Hfa2Zgs3Md7xJy7vAoZwPxtttcUlUOVQv4w/3PwoDVGsoUPsW5+e
6hyirWcH02ttUJsCGmxmCTcJVY5SkwnXXXlZ2Xyqiqxu3MR0AKbMXdta4TPSE/wv3+GP08
d1lFFXmptImduuaIjx6DwC6iSFkkCFIXkWAMWAEKicEkNDq/TDPF17p9iMt0VEhpOniL6w
rBWzVEbBzbOz7tFJ6WL+hWd7wpBXqf9aQE+n0L2O6QzjlgxylwKw+MGrXPYCFmkAR+98A1
vyoAXJzEUqBloEI7GKiGpj+KFdfh6lCN5UQLF2Wl/nogRrd/twOSnmz9u1CdWFMIcJc7O8
M0ymgrtDmi/oTrD9RdgMQGvfeW4BZLDHdt+uObsd2AiSlxuLBqSdWfx7OPSu9oL/kIy2Vc
V6mOtt3PPtzlIZYsaqBBXeIhu1DHOWuednIf1QPo2rKZi2aBYT8/fWgUVW9aAkj8UsC8Pk
P8Mb+qWZk/teK6k82Nn2q41Od4TPgrFD4e3Z1l4Rhu0bgOcAnXjlzmI7pLH8wKByGYT6k4
EAAAdQ3L5mFty+ZhYAAAAHc3NoLXJzYQAAAgEAykcmQLTiSXwIT1OsROmV2OeuL8BKwCN5
92J+JUxy/W8Xr/SJcungqjy3FdFm0ldOKc7Z4BZ/TI0+8m/JnF4Xh6SGlhB+evbDKZqTrc
n5+KevEnHrlwRssjxjCHHzk5J5AEndSWEg+BD5Hfa2Zgs3Md7xJy7vAoZwPxtttcUlUOVQ
v4w/3PwoDVGsoUPsW5+e6hyirWcH02ttUJsCGmxmCTcJVY5SkwnXXXlZ2Xyqiqxu3MR0AK
bMXdta4TPSE/wv3+GP08d1lFFXmptImduuaIjx6DwC6iSFkkCFIXkWAMWAEKicEkNDq/TD
PF17p9iMt0VEhpOniL6wrBWzVEbBzbOz7tFJ6WL+hWd7wpBXqf9aQE+n0L2O6Qzjlgxylw
Kw+MGrXPYCFmkAR+98A1vyoAXJzEUqBloEI7GKiGpj+KFdfh6lCN5UQLF2Wl/nogRrd/tw
OSnmz9u1CdWFMIcJc7O8M0ymgrtDmi/oTrD9RdgMQGvfeW4BZLDHdt+uObsd2AiSlxuLBq
SdWfx7OPSu9oL/kIy2VcV6mOtt3PPtzlIZYsaqBBXeIhu1DHOWuednIf1QPo2rKZi2aBYT
8/fWgUVW9aAkj8UsC8PkP8Mb+qWZk/teK6k82Nn2q41Od4TPgrFD4e3Z1l4Rhu0bgOcAnX
jlzmI7pLH8wKByGYT6k4EAAAADAQABAAACAEeOg+nAE40LY6UsZHS8bVYeH3ClBcySwELT
hOyM7uDYu/hy+Wy9b8zJTbtaKJWgbPY9RrYPP1lFXk9FXH0EjC5f9XyAuT2mrcO5+yQvn0
5ng3dy9XSnDAzBcAc8yH4cAtInTzD2O0OGPZpr/Hp83Tm3NHg4EjVCedLZUSZMZ7cGaFpa
svzp9wE/M2KZNLP087K+Do5pNEuGZVVugH/4eOApqBOsFWoOwTFADJjzkSEdftp6ZM8WMp
XBU5T3UAnh3M3GbartlJqza9o1tKk5Ham9SFZvZFiQMvBaAr6kpzP+qh86hnuvb/EU1Tw1
ldj6skzjJCq3cTzeuIEn7BiUL1qEECjpjx7OG6L9/lWyOy27nU/tiQ1MCUDMs/u/Kpnm8X
1kvEYzq1iEQVjqEaKHQBA35GB5krXzVLK2XNMYzZDM4+bGbffX04t4CpVbJHY7mFrbO584
JlqsCxKvhDDJpNuWhT4HUrAMPCJRvFC57n12+wjLrDsBKMOGRwo1NqnaR75QOR5gtboav+
6P/o35U/gATyiePDF3HD/213gJcOwRXpH9oFleRStqiU2OsfcULlrjD6gIXCAQOOrt4l15
uEh8fnUdFbgmFfuTapKHHm6nVGs6K0JWpqlqlsiwsJxSBwRhRFO3G/iAsmxKDvWaq1yBIJ
yhDRTeA7fyCw8k+wsBAAABAGeNiRwkVyn/iUA61drLC5Y/0Gd+a540VrLMwyV3LGlDZPH3
RQFHH+HldhLqmp2ikHZWFq36vjTDr/ubCuwQNlJo4TAo5/RQk1/ChBqXj2IdT+vBysH+bK
IuZQoWXsfISMfQ7o+F5vv7WdItS9w44HpXayH12Q8D1Qr4Qnt0CeMIhrrV7MPsGVTIOpOU
FxH4xu9ovBWDnyloC4rWkBmeAzLCFtO1V1iGN7Six/OXvnxnbif+BsfdQt+OxHIYBOue5G
+Dkss+1xR8l8xrZsOpN2uY1QFIaE6UyElFleAEhtYL2vvuXTrL3EJKqRtIcWenL/wxYlkt
X1CJQS02JW+PtNUAAAEBAPWFstL1hWK4Fp5ipJSGSkDNvGGuzamAYEgqr6n5Zzb1R1HPyE
x6uEMB7ELQjOG4FENIQYBBnBRnMOWWFJp0V5UjFKDft1FabLiozqBtLCRnHnIGllFIWJK+
u/h9OL4OWXGUJx2Em4XdJBPqp0g56VI237AsnTbTGS0tGLOErLWbQY7npZeBFct/501RTP
M5i7F0QEDLjEDZbDxvCz8a5tjfvyP1awK2SyluiE4VPeYr5Op1JNPTJMz5U3YFsIZxdZHJ
AK5mX8hNzTHpTApkS7o0DvExn5DVB8OHOQFdc+BjBIqQwa953f3FaAw9V3o6Dt1zXe9OJR
tBUiBeurvDFk0AAAEBANLpAv9NDf3c8k0PAYhwu+SWoo0OclOWQSZes/93UeB0ch57LD+v
KVPR3hw2AzAsgZn/PcMbIC3SPLNnAlNftfTa98avQOEfmYqrH499zVPuMb7fieS/eQZ4LF
rsZ0o+W4CDVmzImgOe1hENWcfSeUKajEwpgtj440mJlBls37G/zHMMe5DkA2TAxKldiHOR
fmHOtFKT3fnKFa6PWbwlLFnWIod4zheWrwV7E1coBhh+CA5SlgQANRFs7J8zxPznOtIK2O
cF2+/92cM0TijlBk8u5jnN44cUmk4V1nYboCVb0JD2B7yF9ZYP6IB03jt5GEZSfHHCrZP8
vCxMmXDxtAUAAAAXYWp2YW5lcnBASGVpbWRhbGwubG9jYWwBAgME
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,15 +0,0 @@
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,9B6744BB12A8EA8F
pzZw5s3zDVHYdejZxdTpaRx00Yd1grbJe6mIJGvZRB0Jm0hKXoOX71PUI814mc5+
a5pzbyO98aciL/Eat5m3P692WQ0yOPMuphRnklsM3s4qrCjp2aRRbWvbyV/QV9bp
Xz2yYvNqU3WJC3UJIaFFMvRo/lC/Wsz9OvHSSl3LnsXXhiOCeaE32etoOYdlk9ro
N9NqDdaw28t9//iiHhuQK4afK6TZkU6DatFljJHILCC416Xh9+DDK9E+CDKzmlcw
jSwtzgFKEhgrT0XKoZR9LJZDolT1YpFy7M3cFRYIuYvJfuLcjxVEldJE900QlaJS
ybb6RxV6SRVwQYXTbIClcXes+oNJMv59DivAfajxECQC5sAynW/FnY1sz0igmz6D
scclJuJIbawqiuV/Lv6bvgzMa/ZXL4b9JeJPuQELa7tCpvj4fpNk1IiftYISlwoT
iG5pL8yLhPL4/fxGnKJzUPCA9mbwiloW2cAZZxTd+Utqmhemcl9gF0JGNR2XeYwS
3obEjbkqMF0WR3AcVZU9B5d9SKUaAzTp4vu5yZtNVEIaiVlnI3hMwWMs2Jgahswo
QF9MCPsRYsxLs7/u4a4qoQ==
-----END DSA PRIVATE KEY-----

View File

@@ -1,26 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.backport;
public class JavaVersion {
public static boolean isJava7OrEarlier() {
String property = System.getProperty("java.specification.version");
float diff = Float.parseFloat(property) - 1.7f;
return diff < 0.01;
}
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.backport;
import net.schmizz.sshj.common.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
public class Jdk7HttpProxySocket extends Socket {
private Proxy httpProxy = null;
public Jdk7HttpProxySocket(Proxy proxy) {
super(proxy.type() == Proxy.Type.HTTP ? Proxy.NO_PROXY : proxy);
if (proxy.type() == Proxy.Type.HTTP) {
this.httpProxy = proxy;
}
}
@Override
public void connect(SocketAddress endpoint, int timeout) throws IOException {
if (httpProxy != null) {
connectHttpProxy(endpoint, timeout);
} else {
super.connect(endpoint, timeout);
}
}
private void connectHttpProxy(SocketAddress endpoint, int timeout) throws IOException {
super.connect(httpProxy.address(), timeout);
if (!(endpoint instanceof InetSocketAddress)) {
throw new SocketException("Expected an InetSocketAddress to connect to, got: " + endpoint);
}
InetSocketAddress isa = (InetSocketAddress) endpoint;
String httpConnect = "CONNECT " + isa.getHostName() + ":" + isa.getPort() + " HTTP/1.0\n\n";
getOutputStream().write(httpConnect.getBytes(IOUtils.UTF8));
checkAndFlushProxyResponse();
}
private void checkAndFlushProxyResponse()throws IOException {
InputStream socketInput = getInputStream();
byte[] tmpBuffer = new byte[512];
int len = socketInput.read(tmpBuffer, 0, tmpBuffer.length);
if (len == 0) {
throw new SocketException("Empty response from proxy");
}
String proxyResponse = new String(tmpBuffer, 0, len, IOUtils.UTF8);
// Expecting HTTP/1.x 200 OK
if (proxyResponse.contains("200")) {
// Flush any outstanding message in buffer
if (socketInput.available() > 0) {
socketInput.skip(socketInput.available());
}
// Proxy Connect Successful
} else {
throw new SocketException("Fail to create Socket\nResponse was:" + proxyResponse);
}
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.backport;
import java.io.Closeable;
import java.io.IOException;
import java.net.Socket;
public class Sockets {
/**
* Java 7 and up have Socket implemented as Closeable, whereas Java6 did not have this inheritance.
* @param socket The socket to wrap as Closeable
* @return The (potentially wrapped) Socket as a Closeable.
*/
public static Closeable asCloseable(final Socket socket) {
if (Closeable.class.isAssignableFrom(socket.getClass())) {
return Closeable.class.cast(socket);
} else {
return new Closeable() {
@Override
public void close() throws IOException {
socket.close();
}
};
}
}
}

View File

@@ -1,70 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.secg;
import net.schmizz.sshj.common.SSHRuntimeException;
import java.math.BigInteger;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.Arrays;
public class SecgUtils {
/**
* SECG 2.3.4 Octet String to ECPoint
*/
public static ECPoint getDecoded(byte[] M, EllipticCurve curve) {
int elementSize = getElementSize(curve);
if (M.length != 2 * elementSize + 1 || M[0] != 0x04) {
throw new SSHRuntimeException("Invalid 'f' for Elliptic Curve " + curve.toString());
}
byte[] xBytes = new byte[elementSize];
byte[] yBytes = new byte[elementSize];
System.arraycopy(M, 1, xBytes, 0, elementSize);
System.arraycopy(M, 1 + elementSize, yBytes, 0, elementSize);
return new ECPoint(new BigInteger(1, xBytes), new BigInteger(1, yBytes));
}
/**
* SECG 2.3.3 ECPoint to Octet String
*/
public static byte[] getEncoded(ECPoint point, EllipticCurve curve) {
int elementSize = getElementSize(curve);
byte[] M = new byte[2 * elementSize + 1];
M[0] = 0x04;
byte[] xBytes = stripLeadingZeroes(point.getAffineX().toByteArray());
byte[] yBytes = stripLeadingZeroes(point.getAffineY().toByteArray());
System.arraycopy(xBytes, 0, M, 1 + elementSize - xBytes.length, xBytes.length);
System.arraycopy(yBytes, 0, M, 1 + 2 * elementSize - yBytes.length, yBytes.length);
return M;
}
private static byte[] stripLeadingZeroes(byte[] bytes) {
int start = 0;
while (bytes[start] == 0x0) {
start++;
}
return Arrays.copyOfRange(bytes, start, bytes.length);
}
private static int getElementSize(EllipticCurve curve) {
int fieldSize = curve.getField().getFieldSize();
return (fieldSize + 7) / 8;
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.signature;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import net.schmizz.sshj.common.SSHRuntimeException;
import java.util.Arrays;
/**
* Our own extension of the EdDSAPublicKey that comes from ECC-25519, as that class does not implement equality.
* The code uses the equality of the keys as an indicator whether they're the same during host key verification.
*/
public class Ed25519PublicKey extends EdDSAPublicKey {
public Ed25519PublicKey(EdDSAPublicKeySpec spec) {
super(spec);
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("Ed25519");
if (!spec.getParams().getCurve().equals(ed25519.getCurve())) {
throw new SSHRuntimeException("Cannot create Ed25519 Public Key from wrong spec");
}
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Ed25519PublicKey)) {
return false;
}
Ed25519PublicKey otherKey = (Ed25519PublicKey) other;
return Arrays.equals(getAbyte(), otherKey.getAbyte());
}
@Override
public int hashCode() {
return getA().hashCode();
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.signature;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.common.SSHRuntimeException;
import net.schmizz.sshj.signature.AbstractSignature;
import net.schmizz.sshj.signature.Signature;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
public class SignatureEdDSA extends AbstractSignature {
public static class Factory implements net.schmizz.sshj.common.Factory.Named<Signature> {
@Override
public String getName() {
return KeyType.ED25519.toString();
}
@Override
public Signature create() {
return new SignatureEdDSA();
}
}
SignatureEdDSA() {
super(getEngine());
}
private static EdDSAEngine getEngine() {
try {
return new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
} catch (NoSuchAlgorithmException e) {
throw new SSHRuntimeException(e);
}
}
@Override
public byte[] encode(byte[] signature) {
return signature;
}
@Override
public boolean verify(byte[] sig) {
try {
return signature.verify(extractSig(sig, "ssh-ed25519"));
} catch (SignatureException e) {
throw new SSHRuntimeException(e);
}
}
}

View File

@@ -1,103 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport;
import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.ByteArrayUtils;
import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.transport.TransportException;
import org.slf4j.Logger;
import java.io.IOException;
import java.util.Arrays;
public class IdentificationStringParser {
private final Logger log;
private final Buffer.PlainBuffer buffer;
private byte[] EXPECTED_START_BYTES = new byte[] {'S', 'S', 'H', '-'};
public IdentificationStringParser(Buffer.PlainBuffer buffer) {
this(buffer, LoggerFactory.DEFAULT);
}
public IdentificationStringParser(Buffer.PlainBuffer buffer, LoggerFactory loggerFactory) {
this.log = loggerFactory.getLogger(IdentificationStringParser.class);
this.buffer = buffer;
}
public String parseIdentificationString() throws IOException {
for (;;) {
Buffer.PlainBuffer lineBuffer = new Buffer.PlainBuffer();
int lineStartPos = buffer.rpos();
for (;;) {
if (buffer.available() == 0) {
buffer.rpos(lineStartPos);
return "";
}
byte b = buffer.readByte();
lineBuffer.putByte(b);
if (b == '\n') {
if (checkForIdentification(lineBuffer)) {
return readIdentification(lineBuffer);
} else {
logHeaderLine(lineBuffer);
}
break;
}
}
}
}
private void logHeaderLine(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException {
byte[] bytes = new byte[lineBuffer.available()];
lineBuffer.readRawBytes(bytes);
String header = new String(bytes, 0, bytes.length - 1);
log.debug("Received header: {}", header);
}
private String readIdentification(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException, TransportException {
byte[] bytes = new byte[lineBuffer.available()];
lineBuffer.readRawBytes(bytes);
if (bytes.length > 255) {
log.error("Incorrect identification String received, line was longer than expected: {}", new String(bytes));
log.error("Just for good measure, bytes were: {}", ByteArrayUtils.printHex(bytes, 0, bytes.length));
throw new TransportException("Incorrect identification: line too long: " + ByteArrayUtils.printHex(bytes, 0, bytes.length));
}
if (bytes[bytes.length - 2] != '\r') {
String ident = new String(bytes, 0, bytes.length - 1);
log.warn("Server identification has bad line ending, was expecting a '\\r\\n' however got: '{}' (hex: {})", (char) (bytes[bytes.length - 2] & 0xFF), Integer.toHexString(bytes[bytes.length - 2] & 0xFF));
log.warn("Will treat the identification of this server '{}' leniently", ident);
return ident;
// log.error("Data received up til here was: {}", new String(bytes));
// throw new TransportException("Incorrect identification: bad line ending: " + ByteArrayUtils.toHex(bytes, 0, bytes.length));
}
// Strip off the \r\n
return new String(bytes, 0, bytes.length - 2);
}
private boolean checkForIdentification(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException {
if (lineBuffer.available() < 4) {
return false;
}
byte[] buf = new byte[4];
lineBuffer.readRawBytes(buf);
// Reset
lineBuffer.rpos(0);
return Arrays.equals(EXPECTED_START_BYTES, buf);
}
}

View File

@@ -1,162 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.BlockCipher;
import net.schmizz.sshj.transport.cipher.Cipher;
/**
* All BlockCiphers supported by SSH according to the following RFCs:
*
* <ul>
* <li>https://tools.ietf.org/html/rfc4344#section-3.1</li>
* <li>https://tools.ietf.org/html/rfc4253#section-6.3</li>
* <li>TODO: https://tools.ietf.org/html/rfc5647</li>
* </ul>
*
* Some of the Ciphers are still implemented in net.schmizz.sshj.transport.cipher.*. These are deprecated and scheduled to be removed.
*/
@SuppressWarnings("PMD.MethodNamingConventions")
public class BlockCiphers {
public static final String COUNTER_MODE = "CTR";
public static final String CIPHER_BLOCK_CHAINING_MODE = "CBC";
public static Factory AES128CTR() {
return new Factory(16, 128, "aes128-ctr", "AES", COUNTER_MODE);
}
public static Factory AES192CTR() {
return new Factory(16, 192, "aes192-ctr", "AES", COUNTER_MODE);
}
public static Factory AES256CTR() {
return new Factory(16, 256, "aes256-ctr", "AES", COUNTER_MODE);
}
public static Factory AES128CBC() {
return new Factory(16, 128, "aes128-cbc", "AES", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory AES192CBC() {
return new Factory(16, 192, "aes192-cbc", "AES", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory AES256CBC() {
return new Factory(16, 256, "aes256-cbc", "AES", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory BlowfishCTR() {
return new Factory(8, 256, "blowfish-ctr", "Blowfish", COUNTER_MODE);
}
public static Factory BlowfishCBC() {
return new Factory(8, 128, "blowfish-cbc", "Blowfish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Twofish128CTR() {
return new Factory(16, 128, "twofish128-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish192CTR() {
return new Factory(16, 192, "twofish192-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish256CTR() {
return new Factory(16, 256, "twofish256-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish128CBC() {
return new Factory(16, 128, "twofish128-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Twofish192CBC() {
return new Factory(16, 192, "twofish192-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Twofish256CBC() {
return new Factory(16, 256, "twofish256-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory TwofishCBC() {
return new Factory(16, 256, "twofish-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent128CTR() {
return new Factory(16, 128, "serpent128-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent192CTR() {
return new Factory(16, 192, "serpent192-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent256CTR() {
return new Factory(16, 256, "serpent256-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent128CBC() {
return new Factory(16, 128, "serpent128-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent192CBC() {
return new Factory(16, 192, "serpent192-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent256CBC() {
return new Factory(16, 256, "serpent256-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory IDEACTR() {
return new Factory(8, 128, "idea-ctr", "IDEA", COUNTER_MODE);
}
public static Factory IDEACBC() {
return new Factory(8, 128, "idea-cbc", "IDEA", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Cast128CTR() {
return new Factory(8, 128, "cast128-ctr", "CAST5", COUNTER_MODE);
}
public static Factory Cast128CBC() {
return new Factory(8, 128, "cast128-cbc", "CAST5", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory TripleDESCTR() {
return new Factory(8, 192, "3des-ctr", "DESede", COUNTER_MODE);
}
public static Factory TripleDESCBC() {
return new Factory(8, 192, "3des-cbc", "DESede", CIPHER_BLOCK_CHAINING_MODE);
}
/** Named factory for BlockCipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
private int keysize;
private String cipher;
private String mode;
private String name;
private int ivsize;
/**
* @param ivsize
* @param keysize The keysize used in bits.
* @param name
* @param cipher
* @param mode
*/
public Factory(int ivsize, int keysize, String name, String cipher, String mode) {
this.name = name;
this.keysize = keysize;
this.cipher = cipher;
this.mode = mode;
this.ivsize = ivsize;
}
@Override
public Cipher create() {
return new BlockCipher(ivsize, keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.cipher;
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.CIPHER_BLOCK_CHAINING_MODE;
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.COUNTER_MODE;
/**
* Set of Block Ciphers that are (not yet) part of any of the official RFCs for SSH, but
* that are either supported by other SSH implementations, or are being pushed for to be
* included in a new RFC.
*
* - http://tools.ietf.org/id/draft-kanno-secsh-camellia-01.txt
*/
@SuppressWarnings("PMD.MethodNamingConventions")
public class ExtendedBlockCiphers {
public static BlockCiphers.Factory Camellia128CTR() {
return new BlockCiphers.Factory(16, 128, "camellia128-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia128CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 128, "camellia128-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia192CTR() {
return new BlockCiphers.Factory(16, 192, "camellia192-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia192CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 192, "camellia192-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia256CTR() {
return new BlockCiphers.Factory(16, 256, "camellia256-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia256CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 256, "camellia256-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia128CBC() {
return new BlockCiphers.Factory(16, 128, "camellia128-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia128CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 128, "camellia128-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia192CBC() {
return new BlockCiphers.Factory(16, 192, "camellia192-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia192CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 192, "camellia192-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia256CBC() {
return new BlockCiphers.Factory(16, 256, "camellia256-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia256CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 256, "camellia256-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.BaseCipher;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
public class StreamCipher extends BaseCipher {
public StreamCipher(int bsize, String algorithm, String transformation) {
super(0, bsize, algorithm, transformation);
}
@Override
protected void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
cipher.init(getMode(mode), getKeySpec(key));
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.Cipher;
/**
* Implementations of the Stream Ciphers that are defined in the RFCs
*
* - https://tools.ietf.org/html/rfc4253#section-6.3
* - https://tools.ietf.org/html/rfc4345
*/
@SuppressWarnings("PMD.MethodNamingConventions")
public class StreamCiphers {
public static Factory Arcfour() {
return new Factory(128, "arcfour", "ARCFOUR", "ECB");
}
public static Factory Arcfour128() {
return new Factory(128, "arcfour128", "RC4", "ECB");
}
public static Factory Arcfour256() {
return new Factory(256, "arcfour256", "RC4", "ECB");
}
/** Named factory for BlockCipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
private int keysize;
private String cipher;
private String mode;
private String name;
/**
* @param keysize The keysize used in bits.
* @param name
* @param cipher
* @param mode
*/
public Factory(int keysize, String name, String cipher, String mode) {
this.name = name;
this.keysize = keysize;
this.cipher = cipher;
this.mode = mode;
}
@Override
public Cipher create() {
return new StreamCipher(keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.kex;
import net.schmizz.sshj.transport.digest.Digest;
import net.schmizz.sshj.transport.kex.AbstractDHG;
import net.schmizz.sshj.transport.kex.DH;
import net.schmizz.sshj.transport.kex.DHBase;
import javax.crypto.spec.DHParameterSpec;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
/**
*
*/
public class DHG extends AbstractDHG {
private BigInteger group;
private BigInteger generator;
public DHG(BigInteger group, BigInteger generator, Digest digest) {
super(new DH(), digest);
this.group = group;
this.generator = generator;
}
@Override
protected void initDH(DHBase dh) throws GeneralSecurityException {
dh.init(new DHParameterSpec(group, generator), trans.getConfig().getRandomFactory());
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.kex;
import net.schmizz.sshj.transport.digest.Digest;
import net.schmizz.sshj.transport.digest.SHA1;
import net.schmizz.sshj.transport.digest.SHA256;
import net.schmizz.sshj.transport.digest.SHA512;
import net.schmizz.sshj.transport.kex.KeyExchange;
import java.math.BigInteger;
import static net.schmizz.sshj.transport.kex.DHGroupData.*;
/**
* Factory methods for Diffie Hellman KEX algorithms based on MODP groups / Oakley Groups
*
* - https://tools.ietf.org/html/rfc4253
* - https://tools.ietf.org/html/draft-ietf-curdle-ssh-modp-dh-sha2-01
*/
@SuppressWarnings("PMD.MethodNamingConventions")
public class DHGroups {
public static DHGroups.Factory Group1SHA1() {
return new DHGroups.Factory("diffie-hellman-group1-sha1", P1, G, new SHA1.Factory());
}
public static DHGroups.Factory Group14SHA1() {
return new DHGroups.Factory("diffie-hellman-group14-sha1", P14, G, new SHA1.Factory());
}
public static DHGroups.Factory Group14SHA256() {
return new DHGroups.Factory("diffie-hellman-group14-sha256", P14, G, new SHA256.Factory());
}
public static DHGroups.Factory Group15SHA512() {
return new DHGroups.Factory("diffie-hellman-group15-sha512", P15, G, new SHA512.Factory());
}
public static DHGroups.Factory Group16SHA512() {
return new DHGroups.Factory("diffie-hellman-group16-sha512", P16, G, new SHA512.Factory());
}
public static DHGroups.Factory Group17SHA512() {
return new DHGroups.Factory("diffie-hellman-group17-sha512", P17, G, new SHA512.Factory());
}
public static DHGroups.Factory Group18SHA512() {
return new DHGroups.Factory("diffie-hellman-group18-sha512", P18, G, new SHA512.Factory());
}
/**
* Named factory for DHG1 key exchange
*/
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<KeyExchange> {
private String name;
private BigInteger group;
private BigInteger generator;
private Factory.Named<Digest> digestFactory;
public Factory(String name, BigInteger group, BigInteger generator, Named<Digest> digestFactory) {
this.name = name;
this.group = group;
this.generator = generator;
this.digestFactory = digestFactory;
}
@Override
public KeyExchange create() {
return new DHG(group, generator, digestFactory.create());
}
@Override
public String getName() {
return name;
}
}
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.kex;
import net.schmizz.sshj.transport.digest.SHA256;
import net.schmizz.sshj.transport.digest.SHA384;
import net.schmizz.sshj.transport.digest.SHA512;
import static net.schmizz.sshj.transport.kex.DHGroupData.*;
/**
* Set of KEX methods that are not in official RFCs but are supported by some SSH servers.
*/
@SuppressWarnings("PMD.MethodNamingConventions")
public class ExtendedDHGroups {
public static DHGroups.Factory Group14SHA256AtSSH() {
return new DHGroups.Factory("diffie-hellman-group14-sha256@ssh.com", P14, G, new SHA256.Factory());
}
public static DHGroups.Factory Group15SHA256() {
return new DHGroups.Factory("diffie-hellman-group15-sha256", P15, G, new SHA256.Factory());
}
public static DHGroups.Factory Group15SHA256AtSSH() {
return new DHGroups.Factory("diffie-hellman-group15-sha256@ssh.com", P15, G, new SHA256.Factory());
}
public static DHGroups.Factory Group15SHA384AtSSH() {
return new DHGroups.Factory("diffie-hellman-group15-sha384@ssh.com", P15, G, new SHA384.Factory());
}
public static DHGroups.Factory Group16SHA256() {
return new DHGroups.Factory("diffie-hellman-group16-sha256", P16, G, new SHA256.Factory());
}
public static DHGroups.Factory Group16SHA384AtSSH() {
return new DHGroups.Factory("diffie-hellman-group16-sha384@ssh.com", P16, G, new SHA384.Factory());
}
public static DHGroups.Factory Group16SHA512AtSSH() {
return new DHGroups.Factory("diffie-hellman-group16-sha512@ssh.com", P16, G, new SHA512.Factory());
}
public static DHGroups.Factory Group18SHA512AtSSH() {
return new DHGroups.Factory("diffie-hellman-group18-sha512@ssh.com", P18, G, new SHA512.Factory());
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.mac;
import net.schmizz.sshj.transport.mac.BaseMAC;
import net.schmizz.sshj.transport.mac.MAC;
@SuppressWarnings("PMD.MethodNamingConventions")
public class Macs {
public static Factory HMACMD5() {
return new Factory("hmac-md5", "HmacMD5", 16, 16, false);
}
public static Factory HMACMD596() {
return new Factory("hmac-md5-96", "HmacMD5", 12, 16, false);
}
public static Factory HMACMD5Etm() {
return new Factory("hmac-md5-etm@openssh.com", "HmacMD5", 16, 16, true);
}
public static Factory HMACMD596Etm() {
return new Factory("hmac-md5-96-etm@openssh.com", "HmacMD5", 12, 16, true);
}
public static Factory HMACRIPEMD160() {
return new Factory("hmac-ripemd160", "HMACRIPEMD160", 20, 20, false);
}
public static Factory HMACRIPEMD16096() {
return new Factory("hmac-ripemd160-96", "HMACRIPEMD160", 12, 20, false);
}
public static Factory HMACRIPEMD160Etm() {
return new Factory("hmac-ripemd160-etm@openssh.com", "HMACRIPEMD160", 20, 20, true);
}
public static Factory HMACRIPEMD160OpenSsh() {
return new Factory("hmac-ripemd160@openssh.com", "HMACRIPEMD160", 20, 20, false);
}
public static Factory HMACSHA1() {
return new Factory("hmac-sha1", "HmacSHA1", 20, 20, false);
}
public static Factory HMACSHA196() {
return new Factory("hmac-sha1-96", "HmacSHA1", 12, 20, false);
}
public static Factory HMACSHA1Etm() {
return new Factory("hmac-sha1-etm@openssh.com", "HmacSHA1", 20, 20, true);
}
public static Factory HMACSHA196Etm() {
return new Factory("hmac-sha1-96@openssh.com", "HmacSHA1", 12, 20, true);
}
public static Factory HMACSHA2256() {
return new Factory("hmac-sha2-256", "HmacSHA256", 32, 32, false);
}
public static Factory HMACSHA2256Etm() {
return new Factory("hmac-sha2-256-etm@openssh.com", "HmacSHA256", 32, 32, true);
}
public static Factory HMACSHA2512() {
return new Factory("hmac-sha2-512", "HmacSHA512", 64, 64, false);
}
public static Factory HMACSHA2512Etm() {
return new Factory("hmac-sha2-512-etm@openssh.com", "HmacSHA512", 64, 64, true);
}
public static class Factory implements net.schmizz.sshj.common.Factory.Named<MAC> {
private String name;
private String algorithm;
private int bSize;
private int defBSize;
private final boolean etm;
public Factory(String name, String algorithm, int bSize, int defBSize, boolean etm) {
this.name = name;
this.algorithm = algorithm;
this.bSize = bSize;
this.defBSize = defBSize;
this.etm = etm;
}
@Override
public String getName() {
return name;
}
@Override
public BaseMAC create() {
return new BaseMAC(algorithm, bSize, defBSize, etm);
}
}
}

View File

@@ -1,152 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.transport.verification;
import net.schmizz.sshj.common.Base64;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.transport.mac.MAC;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import com.hierynomus.sshj.transport.mac.Macs;
public class KnownHostMatchers {
public static HostMatcher createMatcher(String hostEntry) throws SSHException {
if (hostEntry.contains(",")) {
return new AnyHostMatcher(hostEntry);
}
if (hostEntry.startsWith("!")) {
return new NegateHostMatcher(hostEntry);
}
if (hostEntry.startsWith("|1|")) {
return new HashedHostMatcher(hostEntry);
}
if (hostEntry.contains("*") || hostEntry.contains("?")) {
return new WildcardHostMatcher(hostEntry);
}
return new EquiHostMatcher(hostEntry);
}
public interface HostMatcher {
boolean match(String hostname) throws IOException;
}
private static class EquiHostMatcher implements HostMatcher {
private String host;
public EquiHostMatcher(String host) {
this.host = host;
}
@Override
public boolean match(String hostname) {
return host.equals(hostname);
}
}
private static class HashedHostMatcher implements HostMatcher {
private final MAC sha1 = Macs.HMACSHA1().create();
private final String hash;
private final String salt;
private byte[] saltyBytes;
HashedHostMatcher(String hash) throws SSHException {
this.hash = hash;
final String[] hostParts = hash.split("\\|");
if (hostParts.length != 4) {
throw new SSHException("Unrecognized format for hashed hostname");
}
salt = hostParts[2];
}
@Override
public boolean match(String hostname) throws IOException {
return hash.equals(hashHost(hostname));
}
private String hashHost(String host) throws IOException {
sha1.init(getSaltyBytes());
return "|1|" + salt + "|" + Base64.encodeBytes(sha1.doFinal(host.getBytes(IOUtils.UTF8)));
}
private byte[] getSaltyBytes() throws IOException {
if (saltyBytes == null) {
saltyBytes = Base64.decode(salt);
}
return saltyBytes;
}
}
private static class AnyHostMatcher implements HostMatcher {
private final List<HostMatcher> matchers;
AnyHostMatcher(String hostEntry) throws SSHException {
matchers = new ArrayList<HostMatcher>();
for (String subEntry : hostEntry.split(",")) {
matchers.add(KnownHostMatchers.createMatcher(subEntry));
}
}
@Override
public boolean match(String hostname) throws IOException {
for (HostMatcher matcher : matchers) {
if (matcher.match(hostname)) {
return true;
}
}
return false;
}
}
private static class NegateHostMatcher implements HostMatcher {
private final HostMatcher matcher;
NegateHostMatcher(String hostEntry) throws SSHException {
this.matcher = createMatcher(hostEntry.substring(1));
}
@Override
public boolean match(String hostname) throws IOException {
return !matcher.match(hostname);
}
}
private static class WildcardHostMatcher implements HostMatcher {
private final Pattern pattern;
public WildcardHostMatcher(String hostEntry) {
this.pattern = Pattern.compile("^" + hostEntry.replace("[", "\\[").replace("]", "\\]").replace(".", "\\.").replace("*", ".*").replace("?", ".") + "$");
}
@Override
public boolean match(String hostname) throws IOException {
return pattern.matcher(hostname).matches();
}
@Override
public String toString() {
return "WildcardHostMatcher[" + pattern + ']';
}
}
}

View File

@@ -1,258 +0,0 @@
package com.hierynomus.sshj.userauth.certificate;
import java.math.BigInteger;
import java.security.PublicKey;
import java.util.Date;
import java.util.List;
import java.util.Map;
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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.
*/
/**
* Certificate wrapper for public keys, created to help implement
* protocol described here:
*
* https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD
*
* Consumed primarily by net.shmizz.sshj.common.KeyType
*
* @param <T> inner public key type
*/
public class Certificate<T extends PublicKey> implements PublicKey {
private static final long serialVersionUID = 1L;
private final T publicKey;
private final byte[] nonce;
private final BigInteger serial;
private final long type;
private final String id;
private final List<String> validPrincipals;
private final Date validAfter;
private final Date validBefore;
private final Map<String, String> critOptions;
private final Map<String, String> extensions;
private final byte[] signatureKey;
private final byte[] signature;
Certificate(Builder<T> builder) {
this.publicKey = builder.getPublicKey();
this.nonce = builder.getNonce();
this.serial = builder.getSerial();
this.type = builder.getType();
this.id = builder.getId();
this.validPrincipals = builder.getValidPrincipals();
this.validAfter = builder.getValidAfter();
this.validBefore = builder.getValidBefore();
this.critOptions = builder.getCritOptions();
this.extensions = builder.getExtensions();
this.signatureKey = builder.getSignatureKey();
this.signature = builder.getSignature();
}
public static <P extends PublicKey> Builder<P> getBuilder() {
return new Builder<P>();
}
public byte[] getNonce() {
return nonce;
}
public BigInteger getSerial() {
return serial;
}
public long getType() {
return type;
}
public String getId() {
return id;
}
public List<String> getValidPrincipals() {
return validPrincipals;
}
public Date getValidAfter() {
return validAfter;
}
public Date getValidBefore() {
return validBefore;
}
public Map<String, String> getCritOptions() {
return critOptions;
}
public Map<String, String> getExtensions() {
return extensions;
}
public byte[] getSignatureKey() {
return signatureKey;
}
public byte[] getSignature() {
return signature;
}
public T getKey() {
return publicKey;
}
@Override
public byte[] getEncoded() {
return publicKey.getEncoded();
}
@Override
public String getAlgorithm() {
return publicKey.getAlgorithm();
}
@Override
public String getFormat() {
return publicKey.getFormat();
}
public static class Builder<T extends PublicKey> {
private T publicKey;
private byte[] nonce;
private BigInteger serial;
private long type;
private String id;
private List<String> validPrincipals;
private Date validAfter;
private Date validBefore;
private Map<String, String> critOptions;
private Map<String, String> extensions;
private byte[] signatureKey;
private byte[] signature;
public Certificate<T> build() {
return new Certificate<T>(this);
}
public T getPublicKey() {
return publicKey;
}
public Builder<T> publicKey(T publicKey) {
this.publicKey = publicKey;
return this;
}
public byte[] getNonce() {
return nonce;
}
public Builder<T> nonce(byte[] nonce) {
this.nonce = nonce;
return this;
}
public BigInteger getSerial() {
return serial;
}
public Builder<T> serial(BigInteger serial) {
this.serial = serial;
return this;
}
public long getType() {
return type;
}
public Builder<T> type(long type) {
this.type = type;
return this;
}
public String getId() {
return id;
}
public Builder<T> id(String id) {
this.id = id;
return this;
}
public List<String> getValidPrincipals() {
return validPrincipals;
}
public Builder<T> validPrincipals(List<String> validPrincipals) {
this.validPrincipals = validPrincipals;
return this;
}
public Date getValidAfter() {
return validAfter;
}
public Builder<T> validAfter(Date validAfter) {
this.validAfter = validAfter;
return this;
}
public Date getValidBefore() {
return validBefore;
}
public Builder<T> validBefore(Date validBefore) {
this.validBefore = validBefore;
return this;
}
public Map<String, String> getCritOptions() {
return critOptions;
}
public Builder<T> critOptions(Map<String, String> critOptions) {
this.critOptions = critOptions;
return this;
}
public Map<String, String> getExtensions() {
return extensions;
}
public Builder<T> extensions(Map<String, String> extensions) {
this.extensions = extensions;
return this;
}
public byte[] getSignatureKey() {
return signatureKey;
}
public Builder<T> signatureKey(byte[] signatureKey) {
this.signatureKey = signatureKey;
return this;
}
public byte[] getSignature() {
return signature;
}
public Builder<T> signature(byte[] signature) {
this.signature = signature;
return this;
}
}
}

View File

@@ -1,245 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 com.hierynomus.sshj.userauth.keyprovider;
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.schmizz.sshj.common.*;
import net.schmizz.sshj.common.Buffer.PlainBuffer;
import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.userauth.keyprovider.BaseFileKeyProvider;
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.mindrot.jbcrypt.BCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.util.Arrays;
/**
* Reads a key file in the new OpenSSH format.
* The format is described in the following document: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
*/
public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
private static final Logger logger = LoggerFactory.getLogger(OpenSSHKeyV1KeyFile.class);
private static final String BEGIN = "-----BEGIN ";
private static final String END = "-----END ";
private static final byte[] AUTH_MAGIC = "openssh-key-v1\0".getBytes();
public static final String OPENSSH_PRIVATE_KEY = "OPENSSH PRIVATE KEY-----";
public static final String BCRYPT = "bcrypt";
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
@Override
public FileKeyProvider create() {
return new OpenSSHKeyV1KeyFile();
}
@Override
public String getName() {
return KeyFormat.OpenSSHv1.name();
}
}
@Override
protected KeyPair readKeyPair() throws IOException {
BufferedReader reader = new BufferedReader(resource.getReader());
try {
if (!checkHeader(reader)) {
throw new IOException("This key is not in 'openssh-key-v1' format");
}
String keyFile = readKeyFile(reader);
byte[] decode = Base64.decode(keyFile);
PlainBuffer keyBuffer = new PlainBuffer(decode);
return readDecodedKeyPair(keyBuffer);
} catch (GeneralSecurityException e) {
throw new SSHRuntimeException(e);
} finally {
IOUtils.closeQuietly(reader);
}
}
private KeyPair readDecodedKeyPair(final PlainBuffer keyBuffer) throws IOException, GeneralSecurityException {
byte[] bytes = new byte[AUTH_MAGIC.length];
keyBuffer.readRawBytes(bytes); // byte[] AUTH_MAGIC
if (!ByteArrayUtils.equals(bytes, 0, AUTH_MAGIC, 0, AUTH_MAGIC.length)) {
throw new IOException("This key does not contain the 'openssh-key-v1' format magic header");
}
String cipherName = keyBuffer.readString(); // string ciphername
String kdfName = keyBuffer.readString(); // string kdfname
byte[] kdfOptions = keyBuffer.readBytes(); // string kdfoptions
int nrKeys = keyBuffer.readUInt32AsInt(); // int number of keys N; Should be 1
if (nrKeys != 1) {
throw new IOException("We don't support having more than 1 key in the file (yet).");
}
PublicKey publicKey = readPublicKey(new PlainBuffer(keyBuffer.readBytes())); // string publickey1
PlainBuffer privateKeyBuffer = new PlainBuffer(keyBuffer.readBytes()); // string (possibly) encrypted, padded list of private keys
if ("none".equals(cipherName)) {
logger.debug("Reading unencrypted keypair");
return readUnencrypted(privateKeyBuffer, publicKey);
} else {
logger.info("Keypair is encrypted with: " + cipherName + ", " + kdfName + ", " + Arrays.toString(kdfOptions));
PlainBuffer decrypted = decryptBuffer(privateKeyBuffer, cipherName, kdfName, kdfOptions);
return readUnencrypted(decrypted, publicKey);
// throw new IOException("Cannot read encrypted keypair with " + cipherName + " yet.");
}
}
private PlainBuffer decryptBuffer(PlainBuffer privateKeyBuffer, String cipherName, String kdfName, byte[] kdfOptions) throws IOException {
Cipher cipher = createCipher(cipherName);
initializeCipher(kdfName, kdfOptions, cipher);
byte[] array = privateKeyBuffer.array();
cipher.update(array, 0, privateKeyBuffer.available());
return new PlainBuffer(array);
}
private void initializeCipher(String kdfName, byte[] kdfOptions, Cipher cipher) throws Buffer.BufferException {
if (kdfName.equals(BCRYPT)) {
PlainBuffer opts = new PlainBuffer(kdfOptions);
byte[] passphrase = new byte[0];
if (pwdf != null) {
CharBuffer charBuffer = CharBuffer.wrap(pwdf.reqPassword(null));
ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
passphrase = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
}
byte[] keyiv = new byte[48];
new BCrypt().pbkdf(passphrase, opts.readBytes(), opts.readUInt32AsInt(), keyiv);
byte[] key = Arrays.copyOfRange(keyiv, 0, 32);
byte[] iv = Arrays.copyOfRange(keyiv, 32, 48);
cipher.init(Cipher.Mode.Decrypt, key, iv);
} else {
throw new IllegalStateException("No support for KDF '" + kdfName + "'.");
}
}
private Cipher createCipher(String cipherName) {
if (cipherName.equals(BlockCiphers.AES256CTR().getName())) {
return BlockCiphers.AES256CTR().create();
} else if (cipherName.equals(BlockCiphers.AES256CBC().getName())) {
return BlockCiphers.AES256CBC().create();
}
throw new IllegalStateException("Cipher '" + cipherName + "' not currently implemented for openssh-key-v1 format");
}
private PublicKey readPublicKey(final PlainBuffer plainBuffer) throws Buffer.BufferException, GeneralSecurityException {
return KeyType.fromString(plainBuffer.readString()).readPubKeyFromBuffer(plainBuffer);
}
private String readKeyFile(final BufferedReader reader) throws IOException {
StringBuilder sb = new StringBuilder();
String line = reader.readLine();
while (!line.startsWith(END)) {
sb.append(line);
line = reader.readLine();
}
return sb.toString();
}
private boolean checkHeader(final BufferedReader reader) throws IOException {
String line = reader.readLine();
while (line != null && !line.startsWith(BEGIN)) {
line = reader.readLine();
}
line = line.substring(BEGIN.length());
return line.startsWith(OPENSSH_PRIVATE_KEY);
}
private KeyPair readUnencrypted(final PlainBuffer keyBuffer, final PublicKey publicKey) throws IOException, GeneralSecurityException {
int privKeyListSize = keyBuffer.available();
if (privKeyListSize % 8 != 0) {
throw new IOException("The private key section must be a multiple of the block size (8)");
}
int checkInt1 = keyBuffer.readUInt32AsInt(); // uint32 checkint1
int checkInt2 = keyBuffer.readUInt32AsInt(); // uint32 checkint2
if (checkInt1 != checkInt2) {
throw new IOException("The checkInts differed, the key was not correctly decoded.");
}
// The private key section contains both the public key and the private key
String keyType = keyBuffer.readString(); // string keytype
KeyType kt = KeyType.fromString(keyType);
logger.info("Read key type: {}", keyType, kt);
KeyPair kp;
switch (kt) {
case ED25519:
keyBuffer.readBytes(); // string publickey (again...)
keyBuffer.readUInt32(); // length of privatekey+publickey
byte[] privKey = new byte[32];
keyBuffer.readRawBytes(privKey); // string privatekey
keyBuffer.readRawBytes(new byte[32]); // string publickey (again...)
kp = new KeyPair(publicKey, new EdDSAPrivateKey(new EdDSAPrivateKeySpec(privKey, EdDSANamedCurveTable.getByName("Ed25519"))));
break;
case RSA:
BigInteger n = keyBuffer.readMPInt(); // Modulus
keyBuffer.readMPInt(); // Public Exponent
BigInteger d = keyBuffer.readMPInt(); // Private Exponent
keyBuffer.readMPInt(); // iqmp (q^-1 mod p)
keyBuffer.readMPInt(); // p (Prime 1)
keyBuffer.readMPInt(); // q (Prime 2)
kp = new KeyPair(publicKey, SecurityUtils.getKeyFactory("RSA").generatePrivate(new RSAPrivateKeySpec(n, d)));
break;
case ECDSA256:
kp = new KeyPair(publicKey, createECDSAPrivateKey(kt, keyBuffer, "P-256"));
break;
case ECDSA384:
kp = new KeyPair(publicKey, createECDSAPrivateKey(kt, keyBuffer, "P-384"));
break;
case ECDSA521:
kp = new KeyPair(publicKey, createECDSAPrivateKey(kt, keyBuffer, "P-521"));
break;
default:
throw new IOException("Cannot decode keytype " + keyType + " in openssh-key-v1 files (yet).");
}
keyBuffer.readString(); // string comment
byte[] padding = new byte[keyBuffer.available()];
keyBuffer.readRawBytes(padding); // char[] padding
for (int i = 0; i < padding.length; i++) {
if ((int) padding[i] != i + 1) {
throw new IOException("Padding of key format contained wrong byte at position: " + i);
}
}
return kp;
}
private PrivateKey createECDSAPrivateKey(KeyType kt, PlainBuffer buffer, String name) throws GeneralSecurityException, Buffer.BufferException {
kt.readPubKeyFromBuffer(buffer); // Public key
BigInteger s = new BigInteger(1, buffer.readBytes());
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
ECPrivateKeySpec pks = new ECPrivateKeySpec(s, ecCurveSpec);
return SecurityUtils.getKeyFactory("ECDSA").generatePrivate(pks);
}
}

View File

@@ -1,918 +0,0 @@
/* Ported from C to Java by Dmitry Skiba [sahn0], 23/02/08.
* Original: http://cds.xs4all.nl:8081/ecdh/
*/
/* Generic 64-bit integer implementation of Curve25519 ECDH
* Written by Matthijs van Duin, 200608242056
* Public domain.
*
* Based on work by Daniel J Bernstein, http://cr.yp.to/ecdh.html
*/
package djb;
public class Curve25519 {
/* key size */
public static final int KEY_SIZE = 32;
/* 0 */
public static final byte[] ZERO = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* the prime 2^255-19 */
public static final byte[] PRIME = {
(byte)237, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)255,
(byte)255, (byte)255, (byte)255, (byte)127
};
/* group order (a prime near 2^252+2^124) */
public static final byte[] ORDER = {
(byte)237, (byte)211, (byte)245, (byte)92,
(byte)26, (byte)99, (byte)18, (byte)88,
(byte)214, (byte)156, (byte)247, (byte)162,
(byte)222, (byte)249, (byte)222, (byte)20,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)16
};
/********* KEY AGREEMENT *********/
/* Private key clamping
* k [out] your private key for key agreement
* k [in] 32 random bytes
*/
public static final void clamp(byte[] k) {
k[31] &= 0x7F;
k[31] |= 0x40;
k[ 0] &= 0xF8;
}
/* Key-pair generation
* P [out] your public key
* s [out] your private key for signing
* k [out] your private key for key agreement
* k [in] 32 random bytes
* s may be NULL if you don't care
*
* WARNING: if s is not NULL, this function has data-dependent timing */
public static final void keygen(byte[] P, byte[] s, byte[] k) {
clamp(k);
core(P, s, k, null);
}
/* Key agreement
* Z [out] shared secret (needs hashing before use)
* k [in] your private key for key agreement
* P [in] peer's public key
*/
public static final void curve(byte[] Z, byte[] k, byte[] P) {
core(Z, null, k, P);
}
/********* DIGITAL SIGNATURES *********/
/* deterministic EC-KCDSA
*
* s is the private key for signing
* P is the corresponding public key
* Z is the context data (signer public key or certificate, etc)
*
* signing:
*
* m = hash(Z, message)
* x = hash(m, s)
* keygen25519(Y, NULL, x);
* r = hash(Y);
* h = m XOR r
* sign25519(v, h, x, s);
*
* output (v,r) as the signature
*
* verification:
*
* m = hash(Z, message);
* h = m XOR r
* verify25519(Y, v, h, P)
*
* confirm r == hash(Y)
*
* It would seem to me that it would be simpler to have the signer directly do
* h = hash(m, Y) and send that to the recipient instead of r, who can verify
* the signature by checking h == hash(m, Y). If there are any problems with
* such a scheme, please let me know.
*
* Also, EC-KCDSA (like most DS algorithms) picks x random, which is a waste of
* perfectly good entropy, but does allow Y to be calculated in advance of (or
* parallel to) hashing the message.
*/
/* Signature generation primitive, calculates (x-h)s mod q
* v [out] signature value
* h [in] signature hash (of message, signature pub key, and context data)
* x [in] signature private key
* s [in] private key for signing
* returns true on success, false on failure (use different x or h)
*/
public static final boolean sign(byte[] v, byte[] h, byte[] x, byte[] s) {
// v = (x - h) s mod q
int w, i;
byte[] h1 = new byte[32], x1 = new byte[32];
byte[] tmp1 = new byte[64];
byte[] tmp2 = new byte[64];
// Don't clobber the arguments, be nice!
cpy32(h1, h);
cpy32(x1, x);
// Reduce modulo group order
byte[] tmp3=new byte[32];
divmod(tmp3, h1, 32, ORDER, 32);
divmod(tmp3, x1, 32, ORDER, 32);
// v = x1 - h1
// If v is negative, add the group order to it to become positive.
// If v was already positive we don't have to worry about overflow
// when adding the order because v < ORDER and 2*ORDER < 2^256
mula_small(v, x1, 0, h1, 32, -1);
mula_small(v, v , 0, ORDER, 32, 1);
// tmp1 = (x-h)*s mod q
mula32(tmp1, v, s, 32, 1);
divmod(tmp2, tmp1, 64, ORDER, 32);
for (w = 0, i = 0; i < 32; i++)
w |= v[i] = tmp1[i];
return w != 0;
}
/* Signature verification primitive, calculates Y = vP + hG
* Y [out] signature public key
* v [in] signature value
* h [in] signature hash
* P [in] public key
*/
public static final void verify(byte[] Y, byte[] v, byte[] h, byte[] P) {
/* Y = v abs(P) + h G */
byte[] d=new byte[32];
long10[]
p=new long10[]{new long10(),new long10()},
s=new long10[]{new long10(),new long10()},
yx=new long10[]{new long10(),new long10(),new long10()},
yz=new long10[]{new long10(),new long10(),new long10()},
t1=new long10[]{new long10(),new long10(),new long10()},
t2=new long10[]{new long10(),new long10(),new long10()};
int vi = 0, hi = 0, di = 0, nvh=0, i, j, k;
/* set p[0] to G and p[1] to P */
set(p[0], 9);
unpack(p[1], P);
/* set s[0] to P+G and s[1] to P-G */
/* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */
/* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */
x_to_y2(t1[0], t2[0], p[1]); /* t2[0] = Py^2 */
sqrt(t1[0], t2[0]); /* t1[0] = Py or -Py */
j = is_negative(t1[0]); /* ... check which */
t2[0]._0 += 39420360; /* t2[0] = Py^2 + Gy^2 */
mul(t2[1], BASE_2Y, t1[0]);/* t2[1] = 2 Py Gy or -2 Py Gy */
sub(t1[j], t2[0], t2[1]); /* t1[0] = Py^2 + Gy^2 - 2 Py Gy */
add(t1[1-j], t2[0], t2[1]);/* t1[1] = Py^2 + Gy^2 + 2 Py Gy */
cpy(t2[0], p[1]); /* t2[0] = Px */
t2[0]._0 -= 9; /* t2[0] = Px - Gx */
sqr(t2[1], t2[0]); /* t2[1] = (Px - Gx)^2 */
recip(t2[0], t2[1], 0); /* t2[0] = 1/(Px - Gx)^2 */
mul(s[0], t1[0], t2[0]); /* s[0] = t1[0]/(Px - Gx)^2 */
sub(s[0], s[0], p[1]); /* s[0] = t1[0]/(Px - Gx)^2 - Px */
s[0]._0 -= 9 + 486662; /* s[0] = X(P+G) */
mul(s[1], t1[1], t2[0]); /* s[1] = t1[1]/(Px - Gx)^2 */
sub(s[1], s[1], p[1]); /* s[1] = t1[1]/(Px - Gx)^2 - Px */
s[1]._0 -= 9 + 486662; /* s[1] = X(P-G) */
mul_small(s[0], s[0], 1); /* reduce s[0] */
mul_small(s[1], s[1], 1); /* reduce s[1] */
/* prepare the chain */
for (i = 0; i < 32; i++) {
vi = (vi >> 8) ^ (v[i] & 0xFF) ^ ((v[i] & 0xFF) << 1);
hi = (hi >> 8) ^ (h[i] & 0xFF) ^ ((h[i] & 0xFF) << 1);
nvh = ~(vi ^ hi);
di = (nvh & (di & 0x80) >> 7) ^ vi;
di ^= nvh & (di & 0x01) << 1;
di ^= nvh & (di & 0x02) << 1;
di ^= nvh & (di & 0x04) << 1;
di ^= nvh & (di & 0x08) << 1;
di ^= nvh & (di & 0x10) << 1;
di ^= nvh & (di & 0x20) << 1;
di ^= nvh & (di & 0x40) << 1;
d[i] = (byte)di;
}
di = ((nvh & (di & 0x80) << 1) ^ vi) >> 8;
/* initialize state */
set(yx[0], 1);
cpy(yx[1], p[di]);
cpy(yx[2], s[0]);
set(yz[0], 0);
set(yz[1], 1);
set(yz[2], 1);
/* y[0] is (even)P + (even)G
* y[1] is (even)P + (odd)G if current d-bit is 0
* y[1] is (odd)P + (even)G if current d-bit is 1
* y[2] is (odd)P + (odd)G
*/
vi = 0;
hi = 0;
/* and go for it! */
for (i = 32; i--!=0; ) {
vi = (vi << 8) | (v[i] & 0xFF);
hi = (hi << 8) | (h[i] & 0xFF);
di = (di << 8) | (d[i] & 0xFF);
for (j = 8; j--!=0; ) {
mont_prep(t1[0], t2[0], yx[0], yz[0]);
mont_prep(t1[1], t2[1], yx[1], yz[1]);
mont_prep(t1[2], t2[2], yx[2], yz[2]);
k = ((vi ^ vi >> 1) >> j & 1)
+ ((hi ^ hi >> 1) >> j & 1);
mont_dbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0]);
k = (di >> j & 2) ^ ((di >> j & 1) << 1);
mont_add(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1],
p[di >> j & 1]);
mont_add(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2],
s[((vi ^ hi) >> j & 2) >> 1]);
}
}
k = (vi & 1) + (hi & 1);
recip(t1[0], yz[k], 0);
mul(t1[1], yx[k], t1[0]);
pack(t1[1], Y);
}
///////////////////////////////////////////////////////////////////////////
/* sahn0:
* Using this class instead of long[10] to avoid bounds checks. */
private static final class long10 {
public long10() {}
public long10(
long _0, long _1, long _2, long _3, long _4,
long _5, long _6, long _7, long _8, long _9)
{
this._0=_0; this._1=_1; this._2=_2;
this._3=_3; this._4=_4; this._5=_5;
this._6=_6; this._7=_7; this._8=_8;
this._9=_9;
}
public long _0,_1,_2,_3,_4,_5,_6,_7,_8,_9;
}
/********************* radix 2^8 math *********************/
private static final void cpy32(byte[] d, byte[] s) {
int i;
for (i = 0; i < 32; i++)
d[i] = s[i];
}
/* p[m..n+m-1] = q[m..n+m-1] + z * x */
/* n is the size of x */
/* n+m is the size of p and q */
private static final int mula_small(byte[] p,byte[] q,int m,byte[] x,int n,int z) {
int v=0;
for (int i=0;i<n;++i) {
v+=(q[i+m] & 0xFF)+z*(x[i] & 0xFF);
p[i+m]=(byte)v;
v>>=8;
}
return v;
}
/* p += x * y * z where z is a small integer
* x is size 32, y is size t, p is size 32+t
* y is allowed to overlap with p+32 if you don't care about the upper half */
private static final int mula32(byte[] p, byte[] x, byte[] y, int t, int z) {
final int n = 31;
int w = 0;
int i = 0;
for (; i < t; i++) {
int zy = z * (y[i] & 0xFF);
w += mula_small(p, p, i, x, n, zy) +
(p[i+n] & 0xFF) + zy * (x[n] & 0xFF);
p[i+n] = (byte)w;
w >>= 8;
}
p[i+n] = (byte)(w + (p[i+n] & 0xFF));
return w >> 8;
}
/* divide r (size n) by d (size t), returning quotient q and remainder r
* quotient is size n-t+1, remainder is size t
* requires t > 0 && d[t-1] != 0
* requires that r[-1] and d[-1] are valid memory locations
* q may overlap with r+t */
private static final void divmod(byte[] q, byte[] r, int n, byte[] d, int t) {
int rn = 0;
int dt = ((d[t-1] & 0xFF) << 8);
if (t>1) {
dt |= (d[t-2] & 0xFF);
}
while (n-- >= t) {
int z = (rn << 16) | ((r[n] & 0xFF) << 8);
if (n>0) {
z |= (r[n-1] & 0xFF);
}
z/=dt;
rn += mula_small(r,r, n-t+1, d, t, -z);
q[n-t+1] = (byte)((z + rn) & 0xFF); /* rn is 0 or -1 (underflow) */
mula_small(r,r, n-t+1, d, t, -rn);
rn = (r[n] & 0xFF);
r[n] = 0;
}
r[t-1] = (byte)rn;
}
private static final int numsize(byte[] x,int n) {
while (n--!=0 && x[n]==0)
;
return n+1;
}
/* Returns x if a contains the gcd, y if b.
* Also, the returned buffer contains the inverse of a mod b,
* as 32-byte signed.
* x and y must have 64 bytes space for temporary use.
* requires that a[-1] and b[-1] are valid memory locations */
private static final byte[] egcd32(byte[] x,byte[] y,byte[] a,byte[] b) {
int an, bn = 32, qn, i;
for (i = 0; i < 32; i++)
x[i] = y[i] = 0;
x[0] = 1;
an = numsize(a, 32);
if (an==0)
return y; /* division by zero */
byte[] temp=new byte[32];
while (true) {
qn = bn - an + 1;
divmod(temp, b, bn, a, an);
bn = numsize(b, bn);
if (bn==0)
return x;
mula32(y, x, temp, qn, -1);
qn = an - bn + 1;
divmod(temp, a, an, b, bn);
an = numsize(a, an);
if (an==0)
return y;
mula32(x, y, temp, qn, -1);
}
}
/********************* radix 2^25.5 GF(2^255-19) math *********************/
private static final int P25=33554431; /* (1 << 25) - 1 */
private static final int P26=67108863; /* (1 << 26) - 1 */
/* Convert to internal format from little-endian byte format */
private static final void unpack(long10 x,byte[] m) {
x._0 = ((m[0] & 0xFF)) | ((m[1] & 0xFF))<<8 |
(m[2] & 0xFF)<<16 | ((m[3] & 0xFF)& 3)<<24;
x._1 = ((m[3] & 0xFF)&~ 3)>>2 | (m[4] & 0xFF)<<6 |
(m[5] & 0xFF)<<14 | ((m[6] & 0xFF)& 7)<<22;
x._2 = ((m[6] & 0xFF)&~ 7)>>3 | (m[7] & 0xFF)<<5 |
(m[8] & 0xFF)<<13 | ((m[9] & 0xFF)&31)<<21;
x._3 = ((m[9] & 0xFF)&~31)>>5 | (m[10] & 0xFF)<<3 |
(m[11] & 0xFF)<<11 | ((m[12] & 0xFF)&63)<<19;
x._4 = ((m[12] & 0xFF)&~63)>>6 | (m[13] & 0xFF)<<2 |
(m[14] & 0xFF)<<10 | (m[15] & 0xFF) <<18;
x._5 = (m[16] & 0xFF) | (m[17] & 0xFF)<<8 |
(m[18] & 0xFF)<<16 | ((m[19] & 0xFF)& 1)<<24;
x._6 = ((m[19] & 0xFF)&~ 1)>>1 | (m[20] & 0xFF)<<7 |
(m[21] & 0xFF)<<15 | ((m[22] & 0xFF)& 7)<<23;
x._7 = ((m[22] & 0xFF)&~ 7)>>3 | (m[23] & 0xFF)<<5 |
(m[24] & 0xFF)<<13 | ((m[25] & 0xFF)&15)<<21;
x._8 = ((m[25] & 0xFF)&~15)>>4 | (m[26] & 0xFF)<<4 |
(m[27] & 0xFF)<<12 | ((m[28] & 0xFF)&63)<<20;
x._9 = ((m[28] & 0xFF)&~63)>>6 | (m[29] & 0xFF)<<2 |
(m[30] & 0xFF)<<10 | (m[31] & 0xFF) <<18;
}
/* Check if reduced-form input >= 2^255-19 */
private static final boolean is_overflow(long10 x) {
return (
((x._0 > P26-19)) &&
((x._1 & x._3 & x._5 & x._7 & x._9) == P25) &&
((x._2 & x._4 & x._6 & x._8) == P26)
) || (x._9 > P25);
}
/* Convert from internal format to little-endian byte format. The
* number must be in a reduced form which is output by the following ops:
* unpack, mul, sqr
* set -- if input in range 0 .. P25
* If you're unsure if the number is reduced, first multiply it by 1. */
private static final void pack(long10 x,byte[] m) {
int ld = 0, ud = 0;
long t;
ld = (is_overflow(x)?1:0) - ((x._9 < 0)?1:0);
ud = ld * -(P25+1);
ld *= 19;
t = ld + x._0 + (x._1 << 26);
m[ 0] = (byte)t;
m[ 1] = (byte)(t >> 8);
m[ 2] = (byte)(t >> 16);
m[ 3] = (byte)(t >> 24);
t = (t >> 32) + (x._2 << 19);
m[ 4] = (byte)t;
m[ 5] = (byte)(t >> 8);
m[ 6] = (byte)(t >> 16);
m[ 7] = (byte)(t >> 24);
t = (t >> 32) + (x._3 << 13);
m[ 8] = (byte)t;
m[ 9] = (byte)(t >> 8);
m[10] = (byte)(t >> 16);
m[11] = (byte)(t >> 24);
t = (t >> 32) + (x._4 << 6);
m[12] = (byte)t;
m[13] = (byte)(t >> 8);
m[14] = (byte)(t >> 16);
m[15] = (byte)(t >> 24);
t = (t >> 32) + x._5 + (x._6 << 25);
m[16] = (byte)t;
m[17] = (byte)(t >> 8);
m[18] = (byte)(t >> 16);
m[19] = (byte)(t >> 24);
t = (t >> 32) + (x._7 << 19);
m[20] = (byte)t;
m[21] = (byte)(t >> 8);
m[22] = (byte)(t >> 16);
m[23] = (byte)(t >> 24);
t = (t >> 32) + (x._8 << 12);
m[24] = (byte)t;
m[25] = (byte)(t >> 8);
m[26] = (byte)(t >> 16);
m[27] = (byte)(t >> 24);
t = (t >> 32) + ((x._9 + ud) << 6);
m[28] = (byte)t;
m[29] = (byte)(t >> 8);
m[30] = (byte)(t >> 16);
m[31] = (byte)(t >> 24);
}
/* Copy a number */
private static final void cpy(long10 out, long10 in) {
out._0=in._0; out._1=in._1;
out._2=in._2; out._3=in._3;
out._4=in._4; out._5=in._5;
out._6=in._6; out._7=in._7;
out._8=in._8; out._9=in._9;
}
/* Set a number to value, which must be in range -185861411 .. 185861411 */
private static final void set(long10 out, int in) {
out._0=in; out._1=0;
out._2=0; out._3=0;
out._4=0; out._5=0;
out._6=0; out._7=0;
out._8=0; out._9=0;
}
/* Add/subtract two numbers. The inputs must be in reduced form, and the
* output isn't, so to do another addition or subtraction on the output,
* first multiply it by one to reduce it. */
private static final void add(long10 xy, long10 x, long10 y) {
xy._0 = x._0 + y._0; xy._1 = x._1 + y._1;
xy._2 = x._2 + y._2; xy._3 = x._3 + y._3;
xy._4 = x._4 + y._4; xy._5 = x._5 + y._5;
xy._6 = x._6 + y._6; xy._7 = x._7 + y._7;
xy._8 = x._8 + y._8; xy._9 = x._9 + y._9;
}
private static final void sub(long10 xy, long10 x, long10 y) {
xy._0 = x._0 - y._0; xy._1 = x._1 - y._1;
xy._2 = x._2 - y._2; xy._3 = x._3 - y._3;
xy._4 = x._4 - y._4; xy._5 = x._5 - y._5;
xy._6 = x._6 - y._6; xy._7 = x._7 - y._7;
xy._8 = x._8 - y._8; xy._9 = x._9 - y._9;
}
/* Multiply a number by a small integer in range -185861411 .. 185861411.
* The output is in reduced form, the input x need not be. x and xy may point
* to the same buffer. */
private static final long10 mul_small(long10 xy, long10 x, long y) {
long t;
t = (x._8*y);
xy._8 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x._9*y);
xy._9 = (t & ((1 << 25) - 1));
t = 19 * (t >> 25) + (x._0*y);
xy._0 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x._1*y);
xy._1 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x._2*y);
xy._2 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x._3*y);
xy._3 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x._4*y);
xy._4 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x._5*y);
xy._5 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x._6*y);
xy._6 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x._7*y);
xy._7 = (t & ((1 << 25) - 1));
t = (t >> 25) + xy._8;
xy._8 = (t & ((1 << 26) - 1));
xy._9 += (t >> 26);
return xy;
}
/* Multiply two numbers. The output is in reduced form, the inputs need not
* be. */
private static final long10 mul(long10 xy, long10 x, long10 y) {
/* sahn0:
* Using local variables to avoid class access.
* This seem to improve performance a bit...
*/
long
x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4,
x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9;
long
y_0=y._0,y_1=y._1,y_2=y._2,y_3=y._3,y_4=y._4,
y_5=y._5,y_6=y._6,y_7=y._7,y_8=y._8,y_9=y._9;
long t;
t = (x_0*y_8) + (x_2*y_6) + (x_4*y_4) + (x_6*y_2) +
(x_8*y_0) + 2 * ((x_1*y_7) + (x_3*y_5) +
(x_5*y_3) + (x_7*y_1)) + 38 *
(x_9*y_9);
xy._8 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x_0*y_9) + (x_1*y_8) + (x_2*y_7) +
(x_3*y_6) + (x_4*y_5) + (x_5*y_4) +
(x_6*y_3) + (x_7*y_2) + (x_8*y_1) +
(x_9*y_0);
xy._9 = (t & ((1 << 25) - 1));
t = (x_0*y_0) + 19 * ((t >> 25) + (x_2*y_8) + (x_4*y_6)
+ (x_6*y_4) + (x_8*y_2)) + 38 *
((x_1*y_9) + (x_3*y_7) + (x_5*y_5) +
(x_7*y_3) + (x_9*y_1));
xy._0 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x_0*y_1) + (x_1*y_0) + 19 * ((x_2*y_9)
+ (x_3*y_8) + (x_4*y_7) + (x_5*y_6) +
(x_6*y_5) + (x_7*y_4) + (x_8*y_3) +
(x_9*y_2));
xy._1 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x_0*y_2) + (x_2*y_0) + 19 * ((x_4*y_8)
+ (x_6*y_6) + (x_8*y_4)) + 2 * (x_1*y_1)
+ 38 * ((x_3*y_9) + (x_5*y_7) +
(x_7*y_5) + (x_9*y_3));
xy._2 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x_0*y_3) + (x_1*y_2) + (x_2*y_1) +
(x_3*y_0) + 19 * ((x_4*y_9) + (x_5*y_8) +
(x_6*y_7) + (x_7*y_6) +
(x_8*y_5) + (x_9*y_4));
xy._3 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x_0*y_4) + (x_2*y_2) + (x_4*y_0) + 19 *
((x_6*y_8) + (x_8*y_6)) + 2 * ((x_1*y_3) +
(x_3*y_1)) + 38 *
((x_5*y_9) + (x_7*y_7) + (x_9*y_5));
xy._4 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x_0*y_5) + (x_1*y_4) + (x_2*y_3) +
(x_3*y_2) + (x_4*y_1) + (x_5*y_0) + 19 *
((x_6*y_9) + (x_7*y_8) + (x_8*y_7) +
(x_9*y_6));
xy._5 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x_0*y_6) + (x_2*y_4) + (x_4*y_2) +
(x_6*y_0) + 19 * (x_8*y_8) + 2 * ((x_1*y_5) +
(x_3*y_3) + (x_5*y_1)) + 38 *
((x_7*y_9) + (x_9*y_7));
xy._6 = (t & ((1 << 26) - 1));
t = (t >> 26) + (x_0*y_7) + (x_1*y_6) + (x_2*y_5) +
(x_3*y_4) + (x_4*y_3) + (x_5*y_2) +
(x_6*y_1) + (x_7*y_0) + 19 * ((x_8*y_9) +
(x_9*y_8));
xy._7 = (t & ((1 << 25) - 1));
t = (t >> 25) + xy._8;
xy._8 = (t & ((1 << 26) - 1));
xy._9 += (t >> 26);
return xy;
}
/* Square a number. Optimization of mul25519(x2, x, x) */
private static final long10 sqr(long10 x2, long10 x) {
long
x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4,
x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9;
long t;
t = (x_4*x_4) + 2 * ((x_0*x_8) + (x_2*x_6)) + 38 *
(x_9*x_9) + 4 * ((x_1*x_7) + (x_3*x_5));
x2._8 = (t & ((1 << 26) - 1));
t = (t >> 26) + 2 * ((x_0*x_9) + (x_1*x_8) + (x_2*x_7) +
(x_3*x_6) + (x_4*x_5));
x2._9 = (t & ((1 << 25) - 1));
t = 19 * (t >> 25) + (x_0*x_0) + 38 * ((x_2*x_8) +
(x_4*x_6) + (x_5*x_5)) + 76 * ((x_1*x_9)
+ (x_3*x_7));
x2._0 = (t & ((1 << 26) - 1));
t = (t >> 26) + 2 * (x_0*x_1) + 38 * ((x_2*x_9) +
(x_3*x_8) + (x_4*x_7) + (x_5*x_6));
x2._1 = (t & ((1 << 25) - 1));
t = (t >> 25) + 19 * (x_6*x_6) + 2 * ((x_0*x_2) +
(x_1*x_1)) + 38 * (x_4*x_8) + 76 *
((x_3*x_9) + (x_5*x_7));
x2._2 = (t & ((1 << 26) - 1));
t = (t >> 26) + 2 * ((x_0*x_3) + (x_1*x_2)) + 38 *
((x_4*x_9) + (x_5*x_8) + (x_6*x_7));
x2._3 = (t & ((1 << 25) - 1));
t = (t >> 25) + (x_2*x_2) + 2 * (x_0*x_4) + 38 *
((x_6*x_8) + (x_7*x_7)) + 4 * (x_1*x_3) + 76 *
(x_5*x_9);
x2._4 = (t & ((1 << 26) - 1));
t = (t >> 26) + 2 * ((x_0*x_5) + (x_1*x_4) + (x_2*x_3))
+ 38 * ((x_6*x_9) + (x_7*x_8));
x2._5 = (t & ((1 << 25) - 1));
t = (t >> 25) + 19 * (x_8*x_8) + 2 * ((x_0*x_6) +
(x_2*x_4) + (x_3*x_3)) + 4 * (x_1*x_5) +
76 * (x_7*x_9);
x2._6 = (t & ((1 << 26) - 1));
t = (t >> 26) + 2 * ((x_0*x_7) + (x_1*x_6) + (x_2*x_5) +
(x_3*x_4)) + 38 * (x_8*x_9);
x2._7 = (t & ((1 << 25) - 1));
t = (t >> 25) + x2._8;
x2._8 = (t & ((1 << 26) - 1));
x2._9 += (t >> 26);
return x2;
}
/* Calculates a reciprocal. The output is in reduced form, the inputs need not
* be. Simply calculates y = x^(p-2) so it's not too fast. */
/* When sqrtassist is true, it instead calculates y = x^((p-5)/8) */
private static final void recip(long10 y, long10 x, int sqrtassist) {
long10
t0=new long10(),
t1=new long10(),
t2=new long10(),
t3=new long10(),
t4=new long10();
int i;
/* the chain for x^(2^255-21) is straight from djb's implementation */
sqr(t1, x); /* 2 == 2 * 1 */
sqr(t2, t1); /* 4 == 2 * 2 */
sqr(t0, t2); /* 8 == 2 * 4 */
mul(t2, t0, x); /* 9 == 8 + 1 */
mul(t0, t2, t1); /* 11 == 9 + 2 */
sqr(t1, t0); /* 22 == 2 * 11 */
mul(t3, t1, t2); /* 31 == 22 + 9
== 2^5 - 2^0 */
sqr(t1, t3); /* 2^6 - 2^1 */
sqr(t2, t1); /* 2^7 - 2^2 */
sqr(t1, t2); /* 2^8 - 2^3 */
sqr(t2, t1); /* 2^9 - 2^4 */
sqr(t1, t2); /* 2^10 - 2^5 */
mul(t2, t1, t3); /* 2^10 - 2^0 */
sqr(t1, t2); /* 2^11 - 2^1 */
sqr(t3, t1); /* 2^12 - 2^2 */
for (i = 1; i < 5; i++) {
sqr(t1, t3);
sqr(t3, t1);
} /* t3 */ /* 2^20 - 2^10 */
mul(t1, t3, t2); /* 2^20 - 2^0 */
sqr(t3, t1); /* 2^21 - 2^1 */
sqr(t4, t3); /* 2^22 - 2^2 */
for (i = 1; i < 10; i++) {
sqr(t3, t4);
sqr(t4, t3);
} /* t4 */ /* 2^40 - 2^20 */
mul(t3, t4, t1); /* 2^40 - 2^0 */
for (i = 0; i < 5; i++) {
sqr(t1, t3);
sqr(t3, t1);
} /* t3 */ /* 2^50 - 2^10 */
mul(t1, t3, t2); /* 2^50 - 2^0 */
sqr(t2, t1); /* 2^51 - 2^1 */
sqr(t3, t2); /* 2^52 - 2^2 */
for (i = 1; i < 25; i++) {
sqr(t2, t3);
sqr(t3, t2);
} /* t3 */ /* 2^100 - 2^50 */
mul(t2, t3, t1); /* 2^100 - 2^0 */
sqr(t3, t2); /* 2^101 - 2^1 */
sqr(t4, t3); /* 2^102 - 2^2 */
for (i = 1; i < 50; i++) {
sqr(t3, t4);
sqr(t4, t3);
} /* t4 */ /* 2^200 - 2^100 */
mul(t3, t4, t2); /* 2^200 - 2^0 */
for (i = 0; i < 25; i++) {
sqr(t4, t3);
sqr(t3, t4);
} /* t3 */ /* 2^250 - 2^50 */
mul(t2, t3, t1); /* 2^250 - 2^0 */
sqr(t1, t2); /* 2^251 - 2^1 */
sqr(t2, t1); /* 2^252 - 2^2 */
if (sqrtassist!=0) {
mul(y, x, t2); /* 2^252 - 3 */
} else {
sqr(t1, t2); /* 2^253 - 2^3 */
sqr(t2, t1); /* 2^254 - 2^4 */
sqr(t1, t2); /* 2^255 - 2^5 */
mul(y, t1, t0); /* 2^255 - 21 */
}
}
/* checks if x is "negative", requires reduced input */
private static final int is_negative(long10 x) {
return (int)(((is_overflow(x) || (x._9 < 0))?1:0) ^ (x._0 & 1));
}
/* a square root */
private static final void sqrt(long10 x, long10 u) {
long10 v=new long10(), t1=new long10(), t2=new long10();
add(t1, u, u); /* t1 = 2u */
recip(v, t1, 1); /* v = (2u)^((p-5)/8) */
sqr(x, v); /* x = v^2 */
mul(t2, t1, x); /* t2 = 2uv^2 */
t2._0--; /* t2 = 2uv^2-1 */
mul(t1, v, t2); /* t1 = v(2uv^2-1) */
mul(x, u, t1); /* x = uv(2uv^2-1) */
}
/********************* Elliptic curve *********************/
/* y^2 = x^3 + 486662 x^2 + x over GF(2^255-19) */
/* t1 = ax + az
* t2 = ax - az */
private static final void mont_prep(long10 t1, long10 t2, long10 ax, long10 az) {
add(t1, ax, az);
sub(t2, ax, az);
}
/* A = P + Q where
* X(A) = ax/az
* X(P) = (t1+t2)/(t1-t2)
* X(Q) = (t3+t4)/(t3-t4)
* X(P-Q) = dx
* clobbers t1 and t2, preserves t3 and t4 */
private static final void mont_add(long10 t1, long10 t2, long10 t3, long10 t4,long10 ax, long10 az, long10 dx) {
mul(ax, t2, t3);
mul(az, t1, t4);
add(t1, ax, az);
sub(t2, ax, az);
sqr(ax, t1);
sqr(t1, t2);
mul(az, t1, dx);
}
/* B = 2 * Q where
* X(B) = bx/bz
* X(Q) = (t3+t4)/(t3-t4)
* clobbers t1 and t2, preserves t3 and t4 */
private static final void mont_dbl(long10 t1, long10 t2, long10 t3, long10 t4,long10 bx, long10 bz) {
sqr(t1, t3);
sqr(t2, t4);
mul(bx, t1, t2);
sub(t2, t1, t2);
mul_small(bz, t2, 121665);
add(t1, t1, bz);
mul(bz, t1, t2);
}
/* Y^2 = X^3 + 486662 X^2 + X
* t is a temporary */
private static final void x_to_y2(long10 t, long10 y2, long10 x) {
sqr(t, x);
mul_small(y2, x, 486662);
add(t, t, y2);
t._0++;
mul(y2, t, x);
}
/* P = kG and s = sign(P)/k */
private static final void core(byte[] Px, byte[] s, byte[] k, byte[] Gx) {
long10
dx=new long10(),
t1=new long10(),
t2=new long10(),
t3=new long10(),
t4=new long10();
long10[]
x=new long10[]{new long10(),new long10()},
z=new long10[]{new long10(),new long10()};
int i, j;
/* unpack the base */
if (Gx!=null)
unpack(dx, Gx);
else
set(dx, 9);
/* 0G = point-at-infinity */
set(x[0], 1);
set(z[0], 0);
/* 1G = G */
cpy(x[1], dx);
set(z[1], 1);
for (i = 32; i--!=0; ) {
if (i==0) {
i=0;
}
for (j = 8; j--!=0; ) {
/* swap arguments depending on bit */
int bit1 = (k[i] & 0xFF) >> j & 1;
int bit0 = ~(k[i] & 0xFF) >> j & 1;
long10 ax = x[bit0];
long10 az = z[bit0];
long10 bx = x[bit1];
long10 bz = z[bit1];
/* a' = a + b */
/* b' = 2 b */
mont_prep(t1, t2, ax, az);
mont_prep(t3, t4, bx, bz);
mont_add(t1, t2, t3, t4, ax, az, dx);
mont_dbl(t1, t2, t3, t4, bx, bz);
}
}
recip(t1, z[0], 0);
mul(dx, x[0], t1);
pack(dx, Px);
/* calculate s such that s abs(P) = G .. assumes G is std base point */
if (s!=null) {
x_to_y2(t2, t1, dx); /* t1 = Py^2 */
recip(t3, z[1], 0); /* where Q=P+G ... */
mul(t2, x[1], t3); /* t2 = Qx */
add(t2, t2, dx); /* t2 = Qx + Px */
t2._0 += 9 + 486662; /* t2 = Qx + Px + Gx + 486662 */
dx._0 -= 9; /* dx = Px - Gx */
sqr(t3, dx); /* t3 = (Px - Gx)^2 */
mul(dx, t2, t3); /* dx = t2 (Px - Gx)^2 */
sub(dx, dx, t1); /* dx = t2 (Px - Gx)^2 - Py^2 */
dx._0 -= 39420360; /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2 */
mul(t1, dx, BASE_R2Y); /* t1 = -Py */
if (is_negative(t1)!=0) /* sign is 1, so just copy */
cpy32(s, k);
else /* sign is -1, so negate */
mula_small(s, ORDER_TIMES_8, 0, k, 32, -1);
/* reduce s mod q
* (is this needed? do it just in case, it's fast anyway) */
//divmod((dstptr) t1, s, 32, order25519, 32);
/* take reciprocal of s mod q */
byte[] temp1=new byte[32];
byte[] temp2=new byte[64];
byte[] temp3=new byte[64];
cpy32(temp1, ORDER);
cpy32(s, egcd32(temp2, temp3, s, temp1));
if ((s[31] & 0x80)!=0)
mula_small(s, s, 0, ORDER, 32, 1);
}
}
/* smallest multiple of the order that's >= 2^255 */
private static final byte[] ORDER_TIMES_8 = {
(byte)104, (byte)159, (byte)174, (byte)231,
(byte)210, (byte)24, (byte)147, (byte)192,
(byte)178, (byte)230, (byte)188, (byte)23,
(byte)245, (byte)206, (byte)247, (byte)166,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)0,
(byte)0, (byte)0, (byte)0, (byte)128
};
/* constants 2Gy and 1/(2Gy) */
private static final long10 BASE_2Y = new long10(
39999547, 18689728, 59995525, 1648697, 57546132,
24010086, 19059592, 5425144, 63499247, 16420658
);
private static final long10 BASE_R2Y = new long10(
5744, 8160848, 4790893, 13779497, 35730846,
12541209, 49101323, 30047407, 40071253, 6226132
);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,23 +19,23 @@ import java.util.Collection;
public class ErrorDeliveryUtil {
public static void alertPromises(Throwable x, Promise<?, ?>... promises) {
for (Promise<?, ?> p : promises)
public static void alertPromises(Throwable x, Promise... promises) {
for (Promise p : promises)
p.deliverError(x);
}
public static void alertPromises(Throwable x, Collection<? extends Promise<?, ?>> promises) {
for (Promise<?, ?> p : promises)
public static void alertPromises(Throwable x, Collection<? extends Promise> promises) {
for (Promise p : promises)
p.deliverError(x);
}
public static void alertEvents(Throwable x, Event<?>... events) {
for (Event<?> e : events)
public static void alertEvents(Throwable x, Event... events) {
for (Event e : events)
e.deliverError(x);
}
public static void alertEvents(Throwable x, Collection<? extends Event<?>> events) {
for (Event<?> e : events)
public static void alertEvents(Throwable x, Collection<? extends Event> events) {
for (Event e : events)
e.deliverError(x);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package net.schmizz.concurrent;
import net.schmizz.sshj.common.LoggerFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -44,8 +42,8 @@ public class Event<T extends Throwable> {
* @param name name of this event
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
*/
public Event(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
promise = new Promise<Object, T>(name, chainer, loggerFactory);
public Event(String name, ExceptionChainer<T> chainer) {
promise = new Promise<Object, T>(name, chainer);
}
/**
@@ -55,8 +53,8 @@ public class Event<T extends Throwable> {
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
* @param lock lock to use
*/
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
promise = new Promise<Object, T>(name, chainer, lock, loggerFactory);
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock) {
promise = new Promise<Object, T>(name, chainer, lock);
}
/** Sets this event to be {@code true}. Short for {@code set(true)}. */
@@ -145,4 +143,4 @@ public class Event<T extends Throwable> {
return promise.toString();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ package net.schmizz.concurrent;
* if (t instanceof SomeException)
* return (SomeException) t;
* else
* return new SomeException(t);
* return new SomeExcepion(t);
* }
* };
* </pre>
@@ -37,4 +37,4 @@ public interface ExceptionChainer<Z extends Throwable> {
Z chain(Throwable t);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
*/
package net.schmizz.concurrent;
import net.schmizz.sshj.common.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -32,7 +32,8 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class Promise<V, T extends Throwable> {
private final Logger log;
private final Logger log = LoggerFactory.getLogger(getClass());
private final String name;
private final ExceptionChainer<T> chainer;
private final ReentrantLock lock;
@@ -48,8 +49,8 @@ public class Promise<V, T extends Throwable> {
* @param name name of this promise
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
*/
public Promise(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
this(name, chainer, null, loggerFactory);
public Promise(String name, ExceptionChainer<T> chainer) {
this(name, chainer, null);
}
/**
@@ -59,11 +60,10 @@ public class Promise<V, T extends Throwable> {
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
* @param lock lock to use
*/
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock) {
this.name = name;
this.chainer = chainer;
this.lock = lock == null ? new ReentrantLock() : lock;
this.log = loggerFactory.getLogger(getClass());
this.cond = this.lock.newCondition();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,16 +19,17 @@ import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.connection.ConnectionImpl;
import net.schmizz.sshj.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class KeepAlive extends Thread {
protected final Logger log;
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final ConnectionImpl conn;
protected int keepAliveInterval = 0;
protected KeepAlive(ConnectionImpl conn, String name) {
this.conn = conn;
log = conn.getTransport().getConfig().getLoggerFactory().getLogger(getClass());
setName(name);
}
@@ -64,8 +65,6 @@ public abstract class KeepAlive extends Thread {
}
Thread.sleep(hi * 1000);
}
} catch (InterruptedException e) {
// Interrupt signal may be catched when sleeping.
} catch (Exception e) {
// If we weren't interrupted, kill the transport, then this exception was unexpected.
// Else we're in shutdown-mode already, so don't forcibly kill the transport.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,13 +22,14 @@ import net.schmizz.sshj.common.SSHPacket;
import net.schmizz.sshj.transport.Transport;
import net.schmizz.sshj.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** An abstract class for {@link Service} that implements common or default functionality. */
public abstract class AbstractService
implements Service {
/** Logger */
protected final Logger log;
protected final Logger log = LoggerFactory.getLogger(getClass());
/** Assigned name of this service */
protected final String name;
@@ -38,7 +39,6 @@ public abstract class AbstractService
public AbstractService(String name, Transport trans) {
this.name = name;
this.trans = trans;
log = trans.getConfig().getLoggerFactory().getLogger(getClass());
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,31 +15,12 @@
*/
package net.schmizz.sshj;
import com.hierynomus.sshj.signature.SignatureEdDSA;
import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.signature.SignatureDSA;
import net.schmizz.sshj.signature.SignatureRSA;
import net.schmizz.sshj.transport.random.JCERandom;
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
/**
* Registers SpongyCastle as JCE provider.
*/
public class AndroidConfig
extends DefaultConfig {
static {
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
}
// don't add ECDSA
protected void initSignatureFactories() {
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory(),
// but add EdDSA
new SignatureEdDSA.Factory());
}
@Override
protected void initRandomFactory(boolean ignored) {
setRandomFactory(new SingletonRandomFactory(new JCERandom.Factory()));

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@ package net.schmizz.sshj;
import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.transport.compression.Compression;
@@ -156,34 +155,4 @@ public interface Config {
* @param keepAliveProvider keep-alive provider
*/
void setKeepAliveProvider(KeepAliveProvider keepAliveProvider);
/**
* Gets whether the client should first wait for a received server ident, before sending the client ident.
* <p/>
* <strong>NB:</strong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
*
* The default value is set to false.
*
* @return Whether to first wait for the server ident.
*/
boolean isWaitForServerIdentBeforeSendingClientIdent();
/**
* Sets whether the SSH client should wait for a received server ident, before sending the client ident.
* <p/>
* <strong>NB:</strong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
* @param waitForServerIdentBeforeSendingClientIdent Whether to wait for the server ident.
*/
void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent);
/**
* Sets the LoggerFactory to use.
*/
void setLoggerFactory(LoggerFactory loggerFactory);
/**
* @return The LoggerFactory the SSHClient will use.
*/
LoggerFactory getLoggerFactory();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@ package net.schmizz.sshj;
import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.transport.compression.Compression;
@@ -45,9 +44,6 @@ public class ConfigImpl
private List<Factory.Named<Signature>> signatureFactories;
private List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories;
private boolean waitForServerIdentBeforeSendingClientIdent = false;
private LoggerFactory loggerFactory;
@Override
public List<Factory.Named<Cipher>> getCipherFactories() {
return cipherFactories;
@@ -161,24 +157,4 @@ public class ConfigImpl
public void setKeepAliveProvider(KeepAliveProvider keepAliveProvider) {
this.keepAliveProvider = keepAliveProvider;
}
@Override
public boolean isWaitForServerIdentBeforeSendingClientIdent() {
return waitForServerIdentBeforeSendingClientIdent;
}
@Override
public void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent) {
this.waitForServerIdentBeforeSendingClientIdent = waitForServerIdentBeforeSendingClientIdent;
}
@Override
public LoggerFactory getLoggerFactory() {
return loggerFactory;
}
@Override
public void setLoggerFactory(LoggerFactory loggerFactory) {
this.loggerFactory = loggerFactory;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,36 +15,44 @@
*/
package net.schmizz.sshj;
import com.hierynomus.sshj.signature.SignatureEdDSA;
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
import com.hierynomus.sshj.transport.kex.DHGroups;
import com.hierynomus.sshj.transport.kex.ExtendedDHGroups;
import com.hierynomus.sshj.transport.mac.Macs;
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.signature.SignatureDSA;
import net.schmizz.sshj.signature.SignatureECDSA;
import net.schmizz.sshj.signature.SignatureRSA;
import net.schmizz.sshj.transport.cipher.*;
import net.schmizz.sshj.transport.cipher.AES128CBC;
import net.schmizz.sshj.transport.cipher.AES128CTR;
import net.schmizz.sshj.transport.cipher.AES192CBC;
import net.schmizz.sshj.transport.cipher.AES192CTR;
import net.schmizz.sshj.transport.cipher.AES256CBC;
import net.schmizz.sshj.transport.cipher.AES256CTR;
import net.schmizz.sshj.transport.cipher.BlowfishCBC;
import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.transport.cipher.TripleDESCBC;
import net.schmizz.sshj.transport.compression.NoneCompression;
import net.schmizz.sshj.transport.kex.Curve25519SHA256;
import net.schmizz.sshj.transport.kex.DHGexSHA1;
import net.schmizz.sshj.transport.kex.DHGexSHA256;
import net.schmizz.sshj.transport.kex.ECDHNistP;
import net.schmizz.sshj.transport.kex.DHG1;
import net.schmizz.sshj.transport.kex.DHG14;
import net.schmizz.sshj.transport.mac.HMACMD5;
import net.schmizz.sshj.transport.mac.HMACMD596;
import net.schmizz.sshj.transport.mac.HMACSHA1;
import net.schmizz.sshj.transport.mac.HMACSHA196;
import net.schmizz.sshj.transport.mac.HMACSHA2256;
import net.schmizz.sshj.transport.mac.HMACSHA2512;
import net.schmizz.sshj.transport.random.BouncyCastleRandom;
import net.schmizz.sshj.transport.random.JCERandom;
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
import net.schmizz.sshj.userauth.keyprovider.PKCS5KeyFile;
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
import org.slf4j.Logger;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* A {@link net.schmizz.sshj.Config} that is initialized as follows. Items marked with an asterisk are added to the config only if
@@ -52,7 +60,9 @@ import java.util.*;
* <p/>
* <ul>
* <li>{@link net.schmizz.sshj.ConfigImpl#setKeyExchangeFactories Key exchange}: {@link net.schmizz.sshj.transport.kex.DHG14}*, {@link net.schmizz.sshj.transport.kex.DHG1}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setCipherFactories Ciphers}: {@link BlockCiphers}, {@link StreamCiphers} [1]</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setCipherFactories Ciphers} [1]: {@link net.schmizz.sshj.transport.cipher.AES128CTR}, {@link net.schmizz.sshj.transport.cipher.AES192CTR}, {@link net.schmizz.sshj.transport.cipher.AES256CTR},
* {@link
* net.schmizz.sshj.transport.cipher.AES128CBC}, {@link net.schmizz.sshj.transport.cipher.AES192CBC}, {@link net.schmizz.sshj.transport.cipher.AES256CBC}, {@link net.schmizz.sshj.transport.cipher.AES192CBC}, {@link net.schmizz.sshj.transport.cipher.TripleDESCBC}, {@link net.schmizz.sshj.transport.cipher.BlowfishCBC}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setMACFactories MAC}: {@link net.schmizz.sshj.transport.mac.HMACSHA1}, {@link net.schmizz.sshj.transport.mac.HMACSHA196}, {@link net.schmizz.sshj.transport.mac.HMACMD5}, {@link
* net.schmizz.sshj.transport.mac.HMACMD596}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setCompressionFactories Compression}: {@link net.schmizz.sshj.transport.compression.NoneCompression}</li>
@@ -69,11 +79,12 @@ import java.util.*;
public class DefaultConfig
extends ConfigImpl {
private Logger log;
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String VERSION = "SSHJ_0_9_2";
public DefaultConfig() {
setLoggerFactory(LoggerFactory.DEFAULT);
setVersion(readVersionFromProperties());
setVersion(VERSION);
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
initKeyExchangeFactories(bouncyCastleRegistered);
initRandomFactory(bouncyCastleRegistered);
@@ -85,52 +96,11 @@ public class DefaultConfig
setKeepAliveProvider(KeepAliveProvider.HEARTBEAT);
}
private String readVersionFromProperties() {
try {
Properties properties = new Properties();
properties.load(DefaultConfig.class.getClassLoader().getResourceAsStream("sshj.properties"));
String property = properties.getProperty("sshj.version");
return "SSHJ_" + property.replace('-', '_'); // '-' is a disallowed character, see RFC-4253#section-4.2
} catch (Exception e) {
log.error("Could not read the sshj.properties file, returning an 'unknown' version as fallback.");
return "SSHJ_VERSION_UNKNOWN";
}
}
@Override
public void setLoggerFactory(LoggerFactory loggerFactory) {
super.setLoggerFactory(loggerFactory);
log = loggerFactory.getLogger(getClass());
}
protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) {
if (bouncyCastleRegistered) {
setKeyExchangeFactories(
new Curve25519SHA256.Factory(),
new Curve25519SHA256.FactoryLibSsh(),
new DHGexSHA256.Factory(),
new ECDHNistP.Factory521(),
new ECDHNistP.Factory384(),
new ECDHNistP.Factory256(),
new DHGexSHA1.Factory(),
DHGroups.Group1SHA1(),
DHGroups.Group14SHA1(),
DHGroups.Group14SHA256(),
DHGroups.Group15SHA512(),
DHGroups.Group16SHA512(),
DHGroups.Group17SHA512(),
DHGroups.Group18SHA512(),
ExtendedDHGroups.Group14SHA256AtSSH(),
ExtendedDHGroups.Group15SHA256(),
ExtendedDHGroups.Group15SHA256AtSSH(),
ExtendedDHGroups.Group15SHA384AtSSH(),
ExtendedDHGroups.Group16SHA256(),
ExtendedDHGroups.Group16SHA384AtSSH(),
ExtendedDHGroups.Group16SHA512AtSSH(),
ExtendedDHGroups.Group18SHA512AtSSH());
} else {
setKeyExchangeFactories(DHGroups.Group1SHA1(), new DHGexSHA1.Factory());
}
if (bouncyCastleRegistered)
setKeyExchangeFactories(new DHG14.Factory(), new DHG1.Factory());
else
setKeyExchangeFactories(new DHG1.Factory());
}
protected void initRandomFactory(boolean bouncyCastleRegistered) {
@@ -140,49 +110,21 @@ public class DefaultConfig
protected void initFileKeyProviderFactories(boolean bouncyCastleRegistered) {
if (bouncyCastleRegistered) {
setFileKeyProviderFactories(
new OpenSSHKeyV1KeyFile.Factory(),
new PKCS8KeyFile.Factory(),
new PKCS5KeyFile.Factory(),
new OpenSSHKeyFile.Factory(),
new PuTTYKeyFile.Factory());
setFileKeyProviderFactories(new PKCS8KeyFile.Factory(), new OpenSSHKeyFile.Factory(), new PuTTYKeyFile.Factory());
}
}
protected void initCipherFactories() {
List<Factory.Named<Cipher>> avail = new LinkedList<Factory.Named<Cipher>>(Arrays.<Factory.Named<Cipher>>asList(
BlockCiphers.AES128CBC(),
BlockCiphers.AES128CTR(),
BlockCiphers.AES192CBC(),
BlockCiphers.AES192CTR(),
BlockCiphers.AES256CBC(),
BlockCiphers.AES256CTR(),
BlockCiphers.BlowfishCBC(),
BlockCiphers.BlowfishCTR(),
BlockCiphers.Cast128CBC(),
BlockCiphers.Cast128CTR(),
BlockCiphers.IDEACBC(),
BlockCiphers.IDEACTR(),
BlockCiphers.Serpent128CBC(),
BlockCiphers.Serpent128CTR(),
BlockCiphers.Serpent192CBC(),
BlockCiphers.Serpent192CTR(),
BlockCiphers.Serpent256CBC(),
BlockCiphers.Serpent256CTR(),
BlockCiphers.TripleDESCBC(),
BlockCiphers.TripleDESCTR(),
BlockCiphers.Twofish128CBC(),
BlockCiphers.Twofish128CTR(),
BlockCiphers.Twofish192CBC(),
BlockCiphers.Twofish192CTR(),
BlockCiphers.Twofish256CBC(),
BlockCiphers.Twofish256CTR(),
BlockCiphers.TwofishCBC(),
StreamCiphers.Arcfour(),
StreamCiphers.Arcfour128(),
StreamCiphers.Arcfour256())
);
new AES128CTR.Factory(),
new AES192CTR.Factory(),
new AES256CTR.Factory(),
new AES128CBC.Factory(),
new AES192CBC.Factory(),
new AES256CBC.Factory(),
new TripleDESCBC.Factory(),
new BlowfishCBC.Factory()));
boolean warn = false;
// Ref. https://issues.apache.org/jira/browse/SSHD-24
@@ -196,7 +138,6 @@ public class DefaultConfig
c.init(Cipher.Mode.Encrypt, key, iv);
} catch (Exception e) {
warn = true;
log.warn(e.getCause().getMessage());
i.remove();
}
}
@@ -204,43 +145,20 @@ public class DefaultConfig
log.warn("Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy");
setCipherFactories(avail);
log.debug("Available cipher factories: {}", avail);
}
protected void initSignatureFactories() {
setSignatureFactories(
new SignatureEdDSA.Factory(),
new SignatureECDSA.Factory256(),
new SignatureECDSA.Factory384(),
new SignatureECDSA.Factory521(),
new SignatureRSA.Factory(),
new SignatureRSA.FactoryCERT(),
new SignatureDSA.Factory()
);
setSignatureFactories(new SignatureECDSA.Factory(), new SignatureRSA.Factory(), new SignatureDSA.Factory());
}
protected void initMACFactories() {
setMACFactories(
Macs.HMACSHA1(),
Macs.HMACSHA1Etm(),
Macs.HMACSHA196(),
Macs.HMACSHA196Etm(),
Macs.HMACMD5(),
Macs.HMACMD5Etm(),
Macs.HMACMD596(),
Macs.HMACMD596Etm(),
Macs.HMACSHA2256(),
Macs.HMACSHA2256Etm(),
Macs.HMACSHA2512(),
Macs.HMACSHA2512Etm(),
Macs.HMACRIPEMD160(),
Macs.HMACRIPEMD160Etm(),
Macs.HMACRIPEMD16096(),
Macs.HMACRIPEMD160OpenSsh()
);
setMACFactories(new HMACSHA1.Factory(), new HMACSHA196.Factory(), new HMACMD5.Factory(),
new HMACMD596.Factory(), new HMACSHA2256.Factory(), new HMACSHA2512.Factory());
}
protected void initCompressionFactories() {
setCompressionFactories(new NoneCompression.Factory());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,11 +15,16 @@
*/
package net.schmizz.sshj;
import net.schmizz.sshj.common.*;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.connection.Connection;
import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.connection.ConnectionImpl;
import net.schmizz.sshj.connection.channel.direct.*;
import net.schmizz.sshj.connection.channel.direct.LocalPortForwarder;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.SessionChannel;
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.connection.channel.forwarded.ConnectListener;
import net.schmizz.sshj.connection.channel.forwarded.RemotePortForwarder;
import net.schmizz.sshj.connection.channel.forwarded.RemotePortForwarder.ForwardedTCPIPChannel;
@@ -34,31 +39,38 @@ import net.schmizz.sshj.transport.TransportImpl;
import net.schmizz.sshj.transport.compression.DelayedZlibCompression;
import net.schmizz.sshj.transport.compression.NoneCompression;
import net.schmizz.sshj.transport.compression.ZlibCompression;
import net.schmizz.sshj.transport.verification.AlgorithmsVerifier;
import net.schmizz.sshj.transport.verification.FingerprintVerifier;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts;
import net.schmizz.sshj.userauth.UserAuth;
import net.schmizz.sshj.userauth.UserAuthException;
import net.schmizz.sshj.userauth.UserAuthImpl;
import net.schmizz.sshj.userauth.keyprovider.*;
import net.schmizz.sshj.userauth.method.*;
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
import net.schmizz.sshj.userauth.keyprovider.KeyPairWrapper;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyProviderUtil;
import net.schmizz.sshj.userauth.method.AuthKeyboardInteractive;
import net.schmizz.sshj.userauth.method.AuthMethod;
import net.schmizz.sshj.userauth.method.AuthPassword;
import net.schmizz.sshj.userauth.method.AuthPublickey;
import net.schmizz.sshj.userauth.method.PasswordResponseProvider;
import net.schmizz.sshj.userauth.password.PasswordFinder;
import net.schmizz.sshj.userauth.password.PasswordUpdateProvider;
import net.schmizz.sshj.userauth.password.PasswordUtils;
import net.schmizz.sshj.userauth.password.Resource;
import net.schmizz.sshj.xfer.scp.SCPFileTransfer;
import org.ietf.jgss.Oid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.LoginContext;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.nio.charset.Charset;
import java.security.KeyPair;
import java.util.*;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* Secure SHell client API.
@@ -109,8 +121,7 @@ public class SSHClient
public static final int DEFAULT_PORT = 22;
/** Logger */
protected final LoggerFactory loggerFactory;
protected final Logger log;
protected final Logger log = LoggerFactory.getLogger(getClass());
/** Transport layer */
protected final Transport trans;
@@ -121,11 +132,6 @@ public class SSHClient
/** {@code ssh-connection} service */
protected final Connection conn;
private final List<LocalPortForwarder> forwarders = new ArrayList<LocalPortForwarder>();
/** character set of the remote machine */
protected Charset remoteCharset = IOUtils.UTF8;
/** Default constructor. Initializes this object using {@link DefaultConfig}. */
public SSHClient() {
this(new DefaultConfig());
@@ -138,8 +144,6 @@ public class SSHClient
*/
public SSHClient(Config config) {
super(DEFAULT_PORT);
loggerFactory = config.getLoggerFactory();
log = loggerFactory.getLogger(getClass());
this.trans = new TransportImpl(config, this);
this.auth = new UserAuthImpl(trans);
this.conn = new ConnectionImpl(trans, config.getKeepAliveProvider());
@@ -149,40 +153,27 @@ public class SSHClient
* Add a {@link HostKeyVerifier} which will be invoked for verifying host key during connection establishment and
* future key exchanges.
*
* @param verifier {@link HostKeyVerifier} instance
* @param hostKeyVerifier {@link HostKeyVerifier} instance
*/
public void addHostKeyVerifier(HostKeyVerifier verifier) {
trans.addHostKeyVerifier(verifier);
}
/**
* Add a {@link AlgorithmsVerifier} which will be invoked for verifying negotiated algorithms.
*
* @param verifier {@link AlgorithmsVerifier} instance
*/
public void addAlgorithmsVerifier(AlgorithmsVerifier verifier) {
trans.addAlgorithmsVerifier(verifier);
public void addHostKeyVerifier(HostKeyVerifier hostKeyVerifier) {
trans.addHostKeyVerifier(hostKeyVerifier);
}
/**
* Add a {@link HostKeyVerifier} that will verify any host that's able to claim a host key with the given {@code
* fingerprint}.
*
* The fingerprint can be specified in either an MD5 colon-delimited format (16 hexadecimal octets, delimited by a colon),
* or in a Base64 encoded format for SHA-1 or SHA-256 fingerprints.
* Valid examples are:
*
* <ul><li>"SHA1:2Fo8c/96zv32xc8GZWbOGYOlRak="</li>
* <li>"SHA256:oQGbQTujGeNIgh0ONthcEpA/BHxtt3rcYY+NxXTxQjs="</li>
* <li>"MD5:d3:5e:40:72:db:08:f1:6d:0c:d7:6d:35:0d:ba:7c:32"</li>
* <li>"d3:5e:40:72:db:08:f1:6d:0c:d7:6d:35:0d:ba:7c:32"</li></ul>
* fingerprint}, e.g. {@code "4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"}
*
* @param fingerprint expected fingerprint in colon-delimited format (16 octets in hex delimited by a colon)
*
* @see SecurityUtils#getFingerprint
*/
public void addHostKeyVerifier(final String fingerprint) {
addHostKeyVerifier(FingerprintVerifier.getInstance(fingerprint));
addHostKeyVerifier(new HostKeyVerifier() {
@Override
public boolean verify(String h, int p, PublicKey k) {
return SecurityUtils.getFingerprint(k).equals(fingerprint);
}
});
}
// FIXME: there are way too many auth... overrides. Better API needed.
@@ -216,7 +207,6 @@ public class SSHClient
checkConnected();
final Deque<UserAuthException> savedEx = new LinkedList<UserAuthException>();
for (AuthMethod method: methods) {
method.setLoggerFactory(loggerFactory);
try {
if (auth.authenticate(username, (Service) conn, method, trans.getTimeoutMs()))
return;
@@ -288,22 +278,6 @@ public class SSHClient
auth(username, new AuthPassword(pfinder), new AuthKeyboardInteractive(new PasswordResponseProvider(pfinder)));
}
/**
* Authenticate {@code username} using the {@code "password"} authentication method and as a fallback basic
* challenge-response authentication.
*
* @param username user to authenticate
* @param pfinder the {@link PasswordFinder} to use for authentication
* @param newPasswordProvider the {@link PasswordUpdateProvider} to use when a new password is being requested from the user.
*
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPassword(String username, PasswordFinder pfinder, PasswordUpdateProvider newPasswordProvider)
throws UserAuthException, TransportException {
auth(username, new AuthPassword(pfinder, newPasswordProvider), new AuthKeyboardInteractive(new PasswordResponseProvider(pfinder)));
}
/**
* Authenticate {@code username} using the {@code "publickey"} authentication method, with keys from some common
* locations on the file system. This method relies on {@code ~/.ssh/id_rsa} and {@code ~/.ssh/id_dsa}.
@@ -318,7 +292,7 @@ public class SSHClient
public void authPublickey(String username)
throws UserAuthException, TransportException {
final String base = System.getProperty("user.home") + File.separator + ".ssh" + File.separator;
authPublickey(username, base + "id_rsa", base + "id_dsa", base + "id_ed25519", base + "id_ecdsa");
authPublickey(username, base + "id_rsa", base + "id_dsa");
}
/**
@@ -356,7 +330,8 @@ public class SSHClient
* @throws TransportException if there was a transport-layer error
*/
public void authPublickey(String username, KeyProvider... keyProviders)
throws UserAuthException, TransportException {
throws UserAuthException,
TransportException {
authPublickey(username, Arrays.<KeyProvider>asList(keyProviders));
}
@@ -390,30 +365,6 @@ public class SSHClient
authPublickey(username, keyProviders);
}
/**
* Authenticate {@code username} using the {@code "gssapi-with-mic"} authentication method, given a login context
* for the peer GSS machine and a list of supported OIDs.
* <p/>
* Supported OIDs should be ordered by preference as the SSH server will choose the first OID that it also
* supports. At least one OID is required
*
* @param username user to authenticate
* @param context {@code LoginContext} for the peer GSS machine
* @param supportedOid first supported OID
* @param supportedOids other supported OIDs
*
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authGssApiWithMic(String username, LoginContext context, Oid supportedOid, Oid... supportedOids)
throws UserAuthException, TransportException {
// insert supportedOid to the front of the list since ordering matters
List<Oid> oids = new ArrayList<Oid>(Arrays.asList(supportedOids));
oids.add(0, supportedOid);
auth(username, new AuthGssApiWithMic(context, oids));
}
/**
* Disconnects from the connected SSH server. {@code SSHClient} objects are not reusable therefore it is incorrect
* to attempt connection after this method has been called.
@@ -424,14 +375,6 @@ public class SSHClient
@Override
public void disconnect()
throws IOException {
for (LocalPortForwarder forwarder : forwarders) {
try {
forwarder.close();
} catch (IOException e) {
log.warn("Error closing forwarder", e);
}
}
forwarders.clear();
trans.disconnect();
super.disconnect();
}
@@ -441,15 +384,6 @@ public class SSHClient
return conn;
}
/**
* Returns the character set used to communicate with the remote machine for certain strings (like paths).
*
* @return remote character set
*/
public Charset getRemoteCharset() {
return remoteCharset;
}
/** @return a {@link RemotePortForwarder} that allows requesting remote forwarding over this connection. */
public RemotePortForwarder getRemotePortForwarder() {
synchronized (conn) {
@@ -515,7 +449,7 @@ public class SSHClient
}
/**
* Utility function for creating a {@link KeyProvider} instance from given location on the file system. Creates a
* Utility function for createing a {@link KeyProvider} instance from given location on the file system. Creates a
* one-off {@link PasswordFinder} using {@link PasswordUtils#createOneOff(char[])}, and calls {@link
* #loadKeys(String, PasswordFinder)}.
*
@@ -534,13 +468,8 @@ public class SSHClient
}
/**
* Creates a {@link KeyProvider} instance from given location on the file system. Currently the following private key files are supported:
* <ul>
* <li>PKCS8 (OpenSSH uses this format)</li>
* <li>PKCS5</li>
* <li>Putty keyfile</li>
* <li>openssh-key-v1 (New OpenSSH keyfile format)</li>
* </ul>
* Creates a {@link KeyProvider} instance from given location on the file system. Currently only PKCS8 format
* private key files are supported (OpenSSH uses this format).
* <p/>
*
* @param location the location of the key file
@@ -645,7 +574,7 @@ public class SSHClient
*/
public void loadKnownHosts(File location)
throws IOException {
addHostKeyVerifier(new OpenSSHKnownHosts(location, loggerFactory));
addHostKeyVerifier(new OpenSSHKnownHosts(location));
}
/**
@@ -661,25 +590,9 @@ public class SSHClient
*
* @return a {@link LocalPortForwarder}
*/
public LocalPortForwarder newLocalPortForwarder(Parameters parameters,
public LocalPortForwarder newLocalPortForwarder(LocalPortForwarder.Parameters parameters,
ServerSocket serverSocket) {
LocalPortForwarder forwarder = new LocalPortForwarder(conn, parameters, serverSocket, loggerFactory);
forwarders.add(forwarder);
return forwarder;
}
/** Create a {@link DirectConnection} channel that connects to a remote address from the server.
*
* This can be used to open a tunnel to, for example, an HTTP server that is only
* accessible from the SSH server, or opening an SSH connection via a 'jump' server.
*
* @param hostname name of the host to connect to from the server.
* @param port remote port number.
*/
public DirectConnection newDirectConnection(String hostname, int port) throws IOException {
DirectConnection tunnel = new DirectConnection(conn, hostname, port);
tunnel.open();
return tunnel;
return new LocalPortForwarder(conn, parameters, serverSocket);
}
/**
@@ -706,7 +619,7 @@ public class SSHClient
public SCPFileTransfer newSCPFileTransfer() {
checkConnected();
checkAuthenticated();
return new SCPFileTransfer(this, loggerFactory);
return new SCPFileTransfer(this);
}
/**
@@ -732,29 +645,19 @@ public class SSHClient
doKex();
}
/**
* Sets the character set used to communicate with the remote machine for certain strings (like paths)
*
* @param remoteCharset
* remote character set or {@code null} for default
*/
public void setRemoteCharset(Charset remoteCharset) {
this.remoteCharset = remoteCharset != null ? remoteCharset : IOUtils.UTF8;
}
@Override
public Session startSession()
throws ConnectionException, TransportException {
checkConnected();
checkAuthenticated();
final SessionChannel sess = new SessionChannel(conn, remoteCharset);
final SessionChannel sess = new SessionChannel(conn);
sess.open();
return sess;
}
/**
* Adds {@code zlib} compression to preferred compression algorithms. There is no guarantee that it will be
* successfully negotiated.
* successfully negotiatied.
* <p/>
* If the client is already connected renegotiation is done; otherwise this method simply returns (and compression
* will be negotiated during connection establishment).
@@ -817,4 +720,4 @@ public class SSHClient
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,11 +15,6 @@
*/
package net.schmizz.sshj;
import com.hierynomus.sshj.backport.JavaVersion;
import com.hierynomus.sshj.backport.Jdk7HttpProxySocket;
import net.schmizz.sshj.connection.channel.Channel;
import net.schmizz.sshj.connection.channel.direct.DirectConnection;
import javax.net.SocketFactory;
import java.io.IOException;
import java.io.InputStream;
@@ -45,149 +40,75 @@ public abstract class SocketClient {
private int timeout = 0;
private String hostname;
private int port;
private boolean tunneled = false;
SocketClient(int defaultPort) {
this.defaultPort = defaultPort;
}
protected InetSocketAddress makeInetSocketAddress(String hostname, int port) {
return new InetSocketAddress(hostname, port);
}
/**
* Connect to a host via a proxy.
* @param hostname The host name to connect to.
* @param proxy The proxy to connect via.
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
*/
@Deprecated
public void connect(String hostname, Proxy proxy) throws IOException {
connect(hostname, defaultPort, proxy);
}
/**
* Connect to a host via a proxy.
* @param hostname The host name to connect to.
* @param port The port to connect to.
* @param proxy The proxy to connect via.
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
*/
@Deprecated
public void connect(String hostname, int port, Proxy proxy) throws IOException {
this.hostname = hostname;
this.port = port;
if (JavaVersion.isJava7OrEarlier() && proxy.type() == Proxy.Type.HTTP) {
// Java7 and earlier have no support for HTTP Connect proxies, return our custom socket.
socket = new Jdk7HttpProxySocket(proxy);
} else {
socket = new Socket(proxy);
}
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
onConnect();
}
/**
* Connect to a host via a proxy.
* @param host The host address to connect to.
* @param proxy The proxy to connect via.
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
*/
@Deprecated
public void connect(InetAddress host, Proxy proxy) throws IOException {
connect(host, defaultPort, proxy);
}
/**
* Connect to a host via a proxy.
* @param host The host address to connect to.
* @param port The port to connect to.
* @param proxy The proxy to connect via.
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
*/
@Deprecated
public void connect(InetAddress host, int port, Proxy proxy) throws IOException {
this.port = port;
if (JavaVersion.isJava7OrEarlier() && proxy.type() == Proxy.Type.HTTP) {
// Java7 and earlier have no support for HTTP Connect proxies, return our custom socket.
socket = new Jdk7HttpProxySocket(proxy);
} else {
socket = new Socket(proxy);
}
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}
public void connect(String hostname) throws IOException {
connect(hostname, defaultPort);
}
public void connect(String hostname, int port) throws IOException {
if (hostname == null) {
connect(InetAddress.getByName(null), port);
} else {
this.hostname = hostname;
this.port = port;
socket = socketFactory.createSocket();
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
onConnect();
}
}
public void connect(String hostname, int port, InetAddress localAddr, int localPort) throws IOException {
if (hostname == null) {
connect(InetAddress.getByName(null), port, localAddr, localPort);
} else {
this.hostname = hostname;
this.port = port;
socket = socketFactory.createSocket();
socket.bind(new InetSocketAddress(localAddr, localPort));
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
onConnect();
}
}
public void connectVia(Channel channel, String hostname, int port) throws IOException {
this.hostname = hostname;
this.port = port;
this.input = channel.getInputStream();
this.output = channel.getOutputStream();
this.tunneled = true;
onConnect();
}
/** Connect to a remote address via a direct TCP/IP connection from the server. */
public void connectVia(DirectConnection directConnection) throws IOException {
connectVia(directConnection, directConnection.getRemoteHost(), directConnection.getRemotePort());
}
public void connect(InetAddress host) throws IOException {
connect(host, defaultPort);
}
public void connect(InetAddress host, int port) throws IOException {
this.port = port;
public void connect(InetAddress host, int port)
throws IOException {
socket = socketFactory.createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}
public void connect(InetAddress host, int port, InetAddress localAddr, int localPort)
public void connect(InetAddress host, int port, Proxy proxy)
throws IOException {
socket = new Socket(proxy);
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}
public void connect(String hostname, int port)
throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port);
}
public void connect(String hostname, int port, Proxy proxy)
throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port, proxy);
}
public void connect(InetAddress host, int port,
InetAddress localAddr, int localPort)
throws IOException {
this.port = port;
socket = socketFactory.createSocket();
socket.bind(new InetSocketAddress(localAddr, localPort));
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}
public void disconnect() throws IOException {
public void connect(String hostname, int port,
InetAddress localAddr, int localPort)
throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port, localAddr, localPort);
}
public void connect(InetAddress host)
throws IOException {
connect(host, defaultPort);
}
public void connect(String hostname)
throws IOException {
connect(hostname, defaultPort);
}
public void connect(InetAddress host, Proxy proxy)
throws IOException {
connect(host, defaultPort, proxy);
}
public void connect(String hostname, Proxy proxy)
throws IOException {
connect(hostname, defaultPort, proxy);
}
public void disconnect()
throws IOException {
if (socket != null) {
socket.close();
socket = null;
@@ -203,15 +124,16 @@ public abstract class SocketClient {
}
public boolean isConnected() {
return tunneled || ((socket != null) && socket.isConnected());
return (socket != null) && socket.isConnected();
}
public int getLocalPort() {
return tunneled ? 65536 : socket.getLocalPort();
return socket.getLocalPort();
}
public InetAddress getLocalAddress() {
return socket == null ? null : socket.getLocalAddress();
return socket.getLocalAddress();
}
public String getRemoteHostname() {
@@ -219,19 +141,18 @@ public abstract class SocketClient {
}
public int getRemotePort() {
return socket == null ? this.port : socket.getPort();
return socket.getPort();
}
public InetAddress getRemoteAddress() {
return socket == null ? null : socket.getInetAddress();
return socket.getInetAddress();
}
public void setSocketFactory(SocketFactory factory) {
if (factory == null) {
if (factory == null)
socketFactory = SocketFactory.getDefault();
} else {
else
socketFactory = factory;
}
}
public SocketFactory getSocketFactory() {
@@ -266,12 +187,11 @@ public abstract class SocketClient {
return output;
}
void onConnect() throws IOException {
if (socket != null) {
socket.setSoTimeout(timeout);
input = socket.getInputStream();
output = socket.getOutputStream();
}
void onConnect()
throws IOException {
socket.setSoTimeout(timeout);
input = socket.getInputStream();
output = socket.getOutputStream();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
*/
package net.schmizz.sshj.common;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.util.Arrays;
@@ -57,11 +57,6 @@ public class Buffer<T extends Buffer<T>> {
/** The maximum valid size of buffer (i.e. biggest power of two that can be represented as an int - 2^30) */
public static final int MAX_SIZE = (1 << 30);
/** Maximum size of a uint64 */
private static final BigInteger MAX_UINT64_VALUE = BigInteger.ONE
.shiftLeft(64)
.subtract(BigInteger.ONE);
protected static int getNextPowerOf2(int i) {
int j = 1;
while (j < i) {
@@ -132,9 +127,8 @@ public class Buffer<T extends Buffer<T>> {
protected void ensureAvailable(int a)
throws BufferException {
if (available() < a) {
if (available() < a)
throw new BufferException("Underflow");
}
}
public void ensureCapacity(int capacity) {
@@ -148,6 +142,7 @@ public class Buffer<T extends Buffer<T>> {
/** Compact this {@link SSHPacket} */
public void compact() {
System.err.println("COMPACTING");
if (available() > 0)
System.arraycopy(data, rpos, data, 0, wpos - rpos);
wpos -= rpos;
@@ -246,7 +241,7 @@ public class Buffer<T extends Buffer<T>> {
* @return this
*/
public T putBytes(byte[] b, int off, int len) {
return putUInt32(len).putRawBytes(b, off, len);
return putUInt32(len - off).putRawBytes(b, off, len);
}
public void readRawBytes(byte[] buf)
@@ -316,7 +311,7 @@ public class Buffer<T extends Buffer<T>> {
public T putUInt32(long uint32) {
ensureCapacity(4);
if (uint32 < 0 || uint32 > 0xffffffffL)
throw new IllegalArgumentException("Invalid value: " + uint32);
throw new RuntimeException("Invalid value: " + uint32);
data[wpos++] = (byte) (uint32 >> 24);
data[wpos++] = (byte) (uint32 >> 16);
data[wpos++] = (byte) (uint32 >> 8);
@@ -348,31 +343,10 @@ public class Buffer<T extends Buffer<T>> {
return uint64;
}
public BigInteger readUInt64AsBigInteger()
throws BufferException {
byte[] magnitude = new byte[8];
readRawBytes(magnitude);
return new BigInteger(1, magnitude);
}
public T putUInt64(long uint64) {
if (uint64 < 0) {
throw new IllegalArgumentException("Invalid value: " + uint64);
}
return putUInt64Unchecked(uint64);
}
public T putUInt64(BigInteger uint64) {
if (uint64.compareTo(MAX_UINT64_VALUE) > 0 ||
uint64.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("Invalid value: " + uint64);
}
return putUInt64Unchecked(uint64.longValue());
}
@SuppressWarnings("unchecked")
private T putUInt64Unchecked(long uint64) {
ensureCapacity(8);
public T putUInt64(long uint64) {
if (uint64 < 0)
throw new RuntimeException("Invalid value: " + uint64);
data[wpos++] = (byte) (uint64 >> 56);
data[wpos++] = (byte) (uint64 >> 48);
data[wpos++] = (byte) (uint64 >> 40);
@@ -387,30 +361,22 @@ public class Buffer<T extends Buffer<T>> {
/**
* Reads an SSH string
*
* @param cs the charset to use for decoding
*
* @return the string as a Java {@code String}
*/
public String readString(Charset cs)
throws BufferException {
int len = readUInt32AsInt();
if (len < 0 || len > 32768) {
throw new BufferException("Bad item length: " + len);
}
ensureAvailable(len);
String s = new String(data, rpos, len, cs);
rpos += len;
return s;
}
/**
* Reads an SSH string using {@code UTF8}
*
* @return the string as a Java {@code String}
*/
public String readString()
throws BufferException {
return readString(IOUtils.UTF8);
int len = readUInt32AsInt();
if (len < 0 || len > 32768)
throw new BufferException("Bad item length: " + len);
ensureAvailable(len);
String s;
try {
s = new String(data, rpos, len, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new SSHRuntimeException(e);
}
rpos += len;
return s;
}
/**
@@ -431,12 +397,8 @@ public class Buffer<T extends Buffer<T>> {
return putBytes(str, offset, len);
}
public T putString(String string, Charset cs) {
return putString(string.getBytes(cs));
}
public T putString(String string) {
return putString(string, IOUtils.UTF8);
return putString(string.getBytes(IOUtils.UTF8));
}
/**
@@ -453,26 +415,21 @@ public class Buffer<T extends Buffer<T>> {
public T putSensitiveString(char[] str) {
if (str == null)
return putString("");
// RFC 4252, Section 8 says: passwords should be encoded as UTF-8.
// RFC 4256, Section 3.4 says: keyboard-interactive information responses should be encoded as UTF-8.
byte[] utf8 = ByteArrayUtils.encodeSensitiveStringToUtf8(str);
putUInt32(utf8.length);
ensureCapacity(utf8.length);
for (byte c : utf8)
data[wpos++] = c;
Arrays.fill(utf8, (byte) 0);
putUInt32(str.length);
ensureCapacity(str.length);
for (char c : str)
data[wpos++] = (byte) c;
Arrays.fill(str, ' ');
return (T) this;
}
public PublicKey readPublicKey()
throws BufferException {
KeyType keyType = KeyType.fromString(readString());
try {
return keyType.readPubKeyFromBuffer(this);
final String type = readString();
return KeyType.fromString(type).readPubKeyFromBuffer(type, this);
} catch (GeneralSecurityException e) {
throw new SSHRuntimeException(e);
} catch (UnsupportedOperationException uoe) {
throw new BufferException("Could not decode keytype " + keyType);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,6 @@
*/
package net.schmizz.sshj.common;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Arrays;
/** Utility functions for byte arrays. */
public class ByteArrayUtils {
@@ -100,56 +94,4 @@ public class ByteArrayUtils {
return sb.toString();
}
public static byte[] parseHex(String hex) {
if (hex == null) {
throw new IllegalArgumentException("Hex string is null");
}
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Hex string '" + hex + "' should have even length.");
}
byte[] result = new byte[hex.length() / 2];
for (int i = 0; i < result.length; i++) {
int hi = parseHexDigit(hex.charAt(i * 2)) << 4;
int lo = parseHexDigit(hex.charAt(i * 2 + 1));
result[i] = (byte) (hi + lo);
}
return result;
}
private static int parseHexDigit(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
}
if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
}
if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
throw new IllegalArgumentException("Digit '" + c + "' out of bounds [0-9a-fA-F]");
}
/**
* Converts a char-array to UTF-8 byte-array and then blanks out source array and all intermediate arrays.
* <p/>
* This is useful when a plaintext password needs to be encoded as UTF-8.
*
* @param str A not-null string as a character array.
*
* @return UTF-8 bytes of the string
*/
public static byte[] encodeSensitiveStringToUtf8(char[] str) {
CharsetEncoder charsetEncoder = Charset.forName("UTF-8").newEncoder();
ByteBuffer utf8Buffer = ByteBuffer.allocate((int) (str.length * charsetEncoder.maxBytesPerChar()));
assert utf8Buffer.hasArray();
charsetEncoder.encode(CharBuffer.wrap(str), utf8Buffer, true);
Arrays.fill(str, ' ');
byte[] utf8Bytes = new byte[utf8Buffer.position()];
System.arraycopy(utf8Buffer.array(), 0, utf8Bytes, 0, utf8Bytes.length);
Arrays.fill(utf8Buffer.array(), (byte) 0);
return utf8Bytes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,113 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 net.schmizz.sshj.common;
import com.hierynomus.sshj.secg.SecgUtils;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.ECKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class ECDSAVariationsAdapter {
private final static String BASE_ALGORITHM_NAME = "ecdsa-sha2-nistp";
private final static Logger log = LoggerFactory.getLogger(ECDSAVariationsAdapter.class);
public final static Map<String, String> SUPPORTED_CURVES = new HashMap<String, String>();
public final static Map<String, String> NIST_CURVES_NAMES = new HashMap<String, String>();
static {
NIST_CURVES_NAMES.put("256", "p-256");
NIST_CURVES_NAMES.put("384", "p-384");
NIST_CURVES_NAMES.put("521", "p-521");
SUPPORTED_CURVES.put("256", "nistp256");
SUPPORTED_CURVES.put("384", "nistp384");
SUPPORTED_CURVES.put("521", "nistp521");
}
static PublicKey readPubKeyFromBuffer(Buffer<?> buf, String variation) throws GeneralSecurityException {
String algorithm = BASE_ALGORITHM_NAME + variation;
if (!SecurityUtils.isBouncyCastleRegistered()) {
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + algorithm);
}
try {
// final String algo = buf.readString(); it has been already read
final String curveName = buf.readString();
final int keyLen = buf.readUInt32AsInt();
final byte x04 = buf.readByte(); // it must be 0x04, but don't think
// we need that check
final byte[] x = new byte[(keyLen - 1) / 2];
final byte[] y = new byte[(keyLen - 1) / 2];
buf.readRawBytes(x);
buf.readRawBytes(y);
if (log.isDebugEnabled()) {
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
algorithm, curveName, keyLen, x04, Arrays.toString(x), Arrays.toString(y)));
}
if (!SUPPORTED_CURVES.values().contains(curveName)) {
throw new GeneralSecurityException(String.format("Unknown curve %s", curveName));
}
BigInteger bigX = new BigInteger(1, x);
BigInteger bigY = new BigInteger(1, y);
String name = NIST_CURVES_NAMES.get(variation);
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
ECPoint p = new ECPoint(bigX, bigY);
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(p, ecCurveSpec);
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
return keyFactory.generatePublic(publicKeySpec);
} catch (Exception ex) {
throw new GeneralSecurityException(ex);
}
}
static void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
final ECPublicKey ecdsa = (ECPublicKey) pk;
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
buf.putString("nistp" + Integer.toString(fieldSizeFromKey(ecdsa)))
.putBytes(encoded);
}
static boolean isECKeyWithFieldSize(Key key, int fieldSize) {
return "ECDSA".equals(key.getAlgorithm())
&& fieldSizeFromKey((ECKey) key) == fieldSize;
}
private static int fieldSizeFromKey(ECKey ecPublicKey) {
return ecPublicKey.getParams().getCurve().getField().getFieldSize();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ import java.util.List;
public interface Factory<T> {
/**
* Interface for a named factory. Named factories are simply factories that are identified by a name. Such names are
* Inteface for a named factory. Named factories are simply factories that are identified by a name. Such names are
* used mainly in SSH algorithm negotiation.
*
* @param <T> type of object created by this factory

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
*/
package net.schmizz.sshj.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
@@ -23,33 +26,25 @@ import java.nio.charset.Charset;
public class IOUtils {
private static final Logger LOG = LoggerFactory.getLogger(IOUtils.class);
public static final Charset UTF8 = Charset.forName("UTF-8");
public static void closeQuietly(Closeable... closeables) {
closeQuietly(LoggerFactory.DEFAULT, closeables);
}
public static ByteArrayOutputStream readFully(InputStream stream)
throws IOException {
return readFully(stream, LoggerFactory.DEFAULT);
}
public static void closeQuietly(LoggerFactory loggerFactory, Closeable... closeables) {
for (Closeable c : closeables) {
for (Closeable c : closeables)
try {
if (c != null)
c.close();
} catch (IOException logged) {
loggerFactory.getLogger(IOUtils.class).warn("Error closing {} - {}", c, logged);
LOG.warn("Error closing {} - {}", c, logged);
}
}
}
public static ByteArrayOutputStream readFully(InputStream stream, LoggerFactory loggerFactory)
public static ByteArrayOutputStream readFully(InputStream stream)
throws IOException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
new StreamCopier(stream, baos, loggerFactory).copy();
new StreamCopier(stream, baos).copy();
return baos;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,36 +15,29 @@
*/
package net.schmizz.sshj.common;
import com.hierynomus.sshj.signature.Ed25519PublicKey;
import com.hierynomus.sshj.userauth.certificate.Certificate;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import net.schmizz.sshj.common.Buffer.BufferException;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.*;
import java.util.Arrays;
/** Type of key e.g. rsa, dsa */
public enum KeyType {
/** SSH identifier for RSA keys */
RSA("ssh-rsa") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
final BigInteger e, n;
try {
@@ -58,22 +51,24 @@ public enum KeyType {
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
final RSAPublicKey rsaKey = (RSAPublicKey) pk;
buf.putMPInt(rsaKey.getPublicExponent()) // e
.putMPInt(rsaKey.getModulus()); // n
buf.putString(sType)
.putMPInt(rsaKey.getPublicExponent()) // e
.putMPInt(rsaKey.getModulus()); // n
}
@Override
protected boolean isMyType(Key key) {
return (key instanceof RSAPublicKey || key instanceof RSAPrivateKey);
}
},
/** SSH identifier for DSA keys */
DSA("ssh-dss") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
BigInteger p, q, g, y;
try {
@@ -89,12 +84,13 @@ public enum KeyType {
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
final DSAPublicKey dsaKey = (DSAPublicKey) pk;
buf.putMPInt(dsaKey.getParams().getP()) // p
.putMPInt(dsaKey.getParams().getQ()) // q
.putMPInt(dsaKey.getParams().getG()) // g
.putMPInt(dsaKey.getY()); // y
buf.putString(sType)
.putMPInt(dsaKey.getParams().getP()) // p
.putMPInt(dsaKey.getParams().getQ()) // q
.putMPInt(dsaKey.getParams().getG()) // g
.putMPInt(dsaKey.getY()); // y
}
@Override
@@ -104,150 +100,95 @@ public enum KeyType {
},
/** SSH identifier for ECDSA-256 keys */
ECDSA256("ecdsa-sha2-nistp256") {
/** SSH identifier for ECDSA keys */
ECDSA("ecdsa-sha2-nistp256") {
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "256");
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf);
}
@Override
protected boolean isMyType(Key key) {
return ECDSAVariationsAdapter.isECKeyWithFieldSize(key, 256);
}
},
/** SSH identifier for ECDSA-384 keys */
ECDSA384("ecdsa-sha2-nistp384") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
throws GeneralSecurityException {
return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "384");
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf);
}
@Override
protected boolean isMyType(Key key) {
return ECDSAVariationsAdapter.isECKeyWithFieldSize(key, 384);
}
},
/** SSH identifier for ECDSA-521 keys */
ECDSA521("ecdsa-sha2-nistp521") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
throws GeneralSecurityException {
return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "521");
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf);
}
@Override
protected boolean isMyType(Key key) {
return ECDSAVariationsAdapter.isECKeyWithFieldSize(key, 521);
}
},
ED25519("ssh-ed25519") {
private final Logger log = LoggerFactory.getLogger(KeyType.class);
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException {
try {
// final String algo = buf.readString(); it has been already read
final String curveName = buf.readString();
final int keyLen = buf.readUInt32AsInt();
final byte[] p = new byte[keyLen];
buf.readRawBytes(p);
if (log.isDebugEnabled()) {
log.debug(String.format("Key algo: %s, Key curve: 25519, Key Len: %s\np: %s",
sType,
final byte x04 = buf.readByte(); // it must be 0x04, but don't think we need that check
final byte[] x = new byte[(keyLen - 1) / 2];
final byte[] y = new byte[(keyLen - 1) / 2];
buf.readRawBytes(x);
buf.readRawBytes(y);
if(log.isDebugEnabled()) {
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
type,
curveName,
keyLen,
Arrays.toString(p))
x04,
Arrays.toString(x),
Arrays.toString(y))
);
}
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("Ed25519");
EdDSAPublicKeySpec publicSpec = new EdDSAPublicKeySpec(p, ed25519);
return new Ed25519PublicKey(publicSpec);
if (!NISTP_CURVE.equals(curveName)) {
throw new GeneralSecurityException(String.format("Unknown curve %s", curveName));
}
} catch (Buffer.BufferException be) {
throw new SSHRuntimeException(be);
BigInteger bigX = new BigInteger(1, x);
BigInteger bigY = new BigInteger(1, y);
X9ECParameters ecParams = NISTNamedCurves.getByName("p-256");
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY, false);
ECParameterSpec spec = new ECParameterSpec(ecParams.getCurve(),
ecParams.getG(), ecParams.getN());
ECPublicKeySpec publicSpec = new ECPublicKeySpec(pPublicPoint, spec);
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
return keyFactory.generatePublic(publicSpec);
} catch (Exception ex) {
throw new GeneralSecurityException(ex);
}
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
EdDSAPublicKey key = (EdDSAPublicKey) pk;
buf.putBytes(key.getAbyte());
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
final ECPublicKey ecdsa = (ECPublicKey) pk;
final java.security.spec.ECPoint point = ecdsa.getW();
final byte[] x = trimStartingZeros(point.getAffineX().toByteArray());
final byte[] y = trimStartingZeros(point.getAffineY().toByteArray());
buf.putString(sType)
.putString(NISTP_CURVE)
.putUInt32(1 + x.length + y.length)
.putRawBytes(new byte[] { (byte) 0x04 })
.putRawBytes(x)
.putRawBytes(y)
;
}
@Override
protected boolean isMyType(Key key) {
return "EdDSA".equals(key.getAlgorithm());
}
},
/** Signed rsa certificate */
RSA_CERT("ssh-rsa-cert-v01@openssh.com") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
throws GeneralSecurityException {
return CertUtils.readPubKey(buf, RSA);
return ("ECDSA".equals(key.getAlgorithm()));
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
CertUtils.writePubKeyContentsIntoBuffer(pk, RSA, buf);
}
private byte[] trimStartingZeros(byte[] in) {
@Override
protected boolean isMyType(Key key) {
return CertUtils.isCertificateOfType(key, RSA);
}
},
/** Signed dsa certificate */
DSA_CERT("ssh-dss-cert-v01@openssh.com") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
throws GeneralSecurityException {
return CertUtils.readPubKey(buf, DSA);
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
CertUtils.writePubKeyContentsIntoBuffer(pk, DSA, buf);
}
@Override
protected boolean isMyType(Key key) {
return CertUtils.isCertificateOfType(key, DSA);
int i = 0;
for (; i < in.length; i++) {
if (in[i] != 0) {
break;
}
}
final byte[] out = new byte[in.length - i];
System.arraycopy(in, i, out, 0, out.length);
return out;
}
},
/** Unrecognized */
UNKNOWN("unknown") {
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
throw new UnsupportedOperationException("Don't know how to decode key:" + sType);
throw new UnsupportedOperationException("Don't know how to decode key:" + type);
}
@Override
@@ -255,31 +196,25 @@ public enum KeyType {
throw new UnsupportedOperationException("Don't know how to encode key: " + pk);
}
@Override
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
throw new UnsupportedOperationException("Don't know how to encode key: " + pk);
}
@Override
protected boolean isMyType(Key key) {
return false;
}
};
private static final String NISTP_CURVE = "nistp256";
protected final String sType;
private KeyType(String type) {
this.sType = type;
}
public abstract PublicKey readPubKeyFromBuffer(Buffer<?> buf)
public abstract PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException;
protected abstract void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf);
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
writePubKeyContentsIntoBuffer(pk, buf.putString(sType));
}
public abstract void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf);
protected abstract boolean isMyType(Key key);
@@ -302,133 +237,4 @@ public enum KeyType {
return sType;
}
static class CertUtils {
@SuppressWarnings("unchecked")
static <T extends PublicKey> Certificate<T> readPubKey(Buffer<?> buf, KeyType innerKeyType) throws GeneralSecurityException {
Certificate.Builder<T> builder = Certificate.getBuilder();
try {
builder.nonce(buf.readBytes());
builder.publicKey((T) innerKeyType.readPubKeyFromBuffer(buf));
builder.serial(buf.readUInt64AsBigInteger());
builder.type(buf.readUInt32());
builder.id(buf.readString());
builder.validPrincipals(unpackList(buf.readBytes()));
builder.validAfter(dateFromEpoch(buf.readUInt64AsBigInteger()));
builder.validBefore(dateFromEpoch(buf.readUInt64AsBigInteger()));
builder.critOptions(unpackMap(buf.readBytes()));
builder.extensions(unpackMap(buf.readBytes()));
buf.readString(); // reserved
builder.signatureKey(buf.readBytes());
builder.signature(buf.readBytes());
} catch (Buffer.BufferException be) {
throw new GeneralSecurityException(be);
}
return builder.build();
}
static void writePubKeyContentsIntoBuffer(PublicKey publicKey, KeyType innerKeyType, Buffer<?> buf) {
Certificate<PublicKey> certificate = toCertificate(publicKey);
buf.putBytes(certificate.getNonce());
innerKeyType.writePubKeyContentsIntoBuffer(certificate.getKey(), buf);
buf.putUInt64(certificate.getSerial())
.putUInt32(certificate.getType())
.putString(certificate.getId())
.putBytes(packList(certificate.getValidPrincipals()))
.putUInt64(epochFromDate(certificate.getValidAfter()))
.putUInt64(epochFromDate(certificate.getValidBefore()))
.putBytes(packMap(certificate.getCritOptions()))
.putBytes(packMap(certificate.getExtensions()))
.putString("") // reserved
.putBytes(certificate.getSignatureKey())
.putBytes(certificate.getSignature());
}
static boolean isCertificateOfType(Key key, KeyType innerKeyType) {
if (!(key instanceof Certificate)) {
return false;
}
@SuppressWarnings("unchecked")
Key innerKey = ((Certificate<PublicKey>) key).getKey();
return innerKeyType.isMyType(innerKey);
}
@SuppressWarnings("unchecked")
static Certificate<PublicKey> toCertificate(PublicKey key) {
if (!(key instanceof Certificate)) {
throw new UnsupportedOperationException("Can't convert non-certificate key " +
key.getAlgorithm() + " to certificate");
}
return ((Certificate<PublicKey>) key);
}
private static Date dateFromEpoch(BigInteger seconds) {
BigInteger maxValue = BigInteger.valueOf(Long.MAX_VALUE / 1000);
if (seconds.compareTo(maxValue) > 0) {
return new Date(maxValue.longValue() * 1000);
} else {
return new Date(seconds.longValue() * 1000);
}
}
private static long epochFromDate(Date date) {
return date.getTime() / 1000;
}
private static String unpackString(byte[] packedString) throws BufferException {
if (packedString.length == 0) {
return "";
}
return new Buffer.PlainBuffer(packedString).readString();
}
private static List<String> unpackList(byte[] packedString) throws BufferException {
List<String> list = new ArrayList<String>();
Buffer<?> buf = new Buffer.PlainBuffer(packedString);
while (buf.available() > 0) {
list.add(buf.readString());
}
return list;
}
private static Map<String, String> unpackMap(byte[] packedString) throws BufferException {
Map<String, String> map = new LinkedHashMap<String, String>();
Buffer<?> buf = new Buffer.PlainBuffer(packedString);
while (buf.available() > 0) {
String name = buf.readString();
String data = unpackString(buf.readStringAsBytes());
map.put(name, data);
}
return map;
}
private static byte[] packString(String data) {
if (data == null || data.isEmpty()) {
return "".getBytes();
}
return new Buffer.PlainBuffer().putString(data).getCompactData();
}
private static byte[] packList(Iterable<String> strings) {
Buffer<?> buf = new Buffer.PlainBuffer();
for (String string : strings) {
buf.putString(string);
}
return buf.getCompactData();
}
private static byte[] packMap(Map<String, String> map) {
Buffer<?> buf = new Buffer.PlainBuffer();
List<String> keys = new ArrayList<String>(map.keySet());
Collections.sort(keys);
for (String key : keys) {
buf.putString(key);
String value = map.get(key);
buf.putString(packString(value));
}
return buf.getCompactData();
}
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* Licensed 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 net.schmizz.sshj.common;
import org.slf4j.Logger;
public interface LoggerFactory {
Logger getLogger(String name);
Logger getLogger(Class<?> clazz);
/**
* Default SLF4J-based implementation of the SSHJ LoggerFactory.
*/
LoggerFactory DEFAULT = new LoggerFactory() {
@Override
public Logger getLogger(String name) {
return org.slf4j.LoggerFactory.getLogger(name);
}
@Override
public Logger getLogger(Class<?> clazz) {
return org.slf4j.LoggerFactory.getLogger(clazz);
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ public enum Message {
KEXDH_INIT(30),
/** { KEXDH_REPLY, KEXDH_GEX_GROUP, SSH_MSG_KEX_ECDH_REPLY } */
/** { KEXDH_REPLY, KEXDH_GEX_GROUP } */
KEXDH_31(31),
KEX_DH_GEX_INIT(32),
@@ -46,9 +46,6 @@ public enum Message {
USERAUTH_60(60),
USERAUTH_INFO_RESPONSE(61),
USERAUTH_GSSAPI_EXCHANGE_COMPLETE(63),
USERAUTH_GSSAPI_MIC(66),
GLOBAL_REQUEST(80),
REQUEST_SUCCESS(81),
REQUEST_FAILURE(82),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ public class SSHRuntimeException
}
public SSHRuntimeException(Throwable cause) {
this(cause.getMessage(), cause);
this(null, cause);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2009 - SSHJ Contributors
/**
* Copyright 2009 sshj contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,90 +15,58 @@
*/
package net.schmizz.sshj.common;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
// TODO refactor
import static java.lang.String.format;
/**
* Static utility method relating to security facilities.
*/
/** Static utility method relating to security facilities. */
public class SecurityUtils {
private static class BouncyCastleRegistration {
public void run()
throws Exception {
if (java.security.Security.getProvider(BOUNCY_CASTLE) == null) {
LOG.debug("Trying to register BouncyCastle as a JCE provider");
java.security.Security.addProvider(new BouncyCastleProvider());
MessageDigest.getInstance("MD5", BOUNCY_CASTLE);
KeyAgreement.getInstance("DH", BOUNCY_CASTLE);
LOG.info("BouncyCastle registration succeeded");
} else
LOG.info("BouncyCastle already registered as a JCE provider");
securityProvider = BOUNCY_CASTLE;
}
}
private static final Logger LOG = LoggerFactory.getLogger(SecurityUtils.class);
/**
* Identifier for the BouncyCastle JCE provider
*/
/** Identifier for the BouncyCastle JCE provider */
public static final String BOUNCY_CASTLE = "BC";
/**
* Identifier for the BouncyCastle JCE provider
*/
public static final String SPONGY_CASTLE = "SC";
/*
* Security provider identifier. null = default JCE
*/
private static String securityProvider = null;
// relate to BC registration (or SpongyCastle on Android)
// relate to BC registration
private static Boolean registerBouncyCastle;
private static boolean registrationDone;
public static boolean registerSecurityProvider(String providerClassName) {
Provider provider = null;
try {
Class<?> name = Class.forName(providerClassName);
provider = (Provider) name.newInstance();
} catch (ClassNotFoundException e) {
LOG.info("Security Provider class '{}' not found", providerClassName);
} catch (InstantiationException e) {
LOG.info("Security Provider class '{}' could not be created", providerClassName);
} catch (IllegalAccessException e) {
LOG.info("Security Provider class '{}' could not be accessed", providerClassName);
}
if (provider == null) {
return false;
}
try {
if (Security.getProvider(provider.getName()) == null) {
Security.addProvider(provider);
}
if (securityProvider == null) {
MessageDigest.getInstance("MD5", provider);
KeyAgreement.getInstance("DH", provider);
setSecurityProvider(provider.getName());
return true;
}
} catch (NoSuchAlgorithmException e) {
LOG.info(format("Security Provider '%s' does not support necessary algorithm", providerClassName), e);
} catch (Exception e) {
LOG.info(format("Registration of Security Provider '%s' unexpectedly failed", providerClassName), e);
}
return false;
}
public static synchronized Cipher getCipher(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
register();
@@ -112,7 +80,9 @@ public class SecurityUtils {
* Computes the fingerprint for a public key, in the standard SSH format, e.g. "4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"
*
* @param key the public key
*
* @return the fingerprint
*
* @see <a href="http://tools.ietf.org/html/draft-friedl-secsh-fingerprint-00">specification</a>
*/
public static String getFingerprint(PublicKey key) {
@@ -135,7 +105,9 @@ public class SecurityUtils {
* Creates a new instance of {@link KeyAgreement} with the given algorithm.
*
* @param algorithm key agreement algorithm
*
* @return new instance
*
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@@ -152,7 +124,9 @@ public class SecurityUtils {
* Creates a new instance of {@link KeyFactory} with the given algorithm.
*
* @param algorithm key factory algorithm e.g. RSA, DSA
*
* @return new instance
*
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@@ -169,7 +143,9 @@ public class SecurityUtils {
* Creates a new instance of {@link KeyPairGenerator} with the given algorithm.
*
* @param algorithm key pair generator algorithm
*
* @return new instance
*
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@@ -186,7 +162,9 @@ public class SecurityUtils {
* Create a new instance of {@link Mac} with the given algorithm.
*
* @param algorithm MAC algorithm
*
* @return new instance
*
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@@ -203,7 +181,9 @@ public class SecurityUtils {
* Create a new instance of {@link MessageDigest} with the given algorithm.
*
* @param algorithm MessageDigest algorithm name
*
* @return new instance
*
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@@ -239,11 +219,11 @@ public class SecurityUtils {
* Attempts registering BouncyCastle as security provider if it has not been previously attempted and returns
* whether the registration succeeded.
*
* @return whether BC (or SC on Android) registered
* @return whether BC registered
*/
public static synchronized boolean isBouncyCastleRegistered() {
register();
return BOUNCY_CASTLE.equals(securityProvider) || SPONGY_CASTLE.equals(securityProvider);
return BOUNCY_CASTLE.equals(securityProvider);
}
public static synchronized void setRegisterBouncyCastle(boolean registerBouncyCastle) {
@@ -263,16 +243,20 @@ public class SecurityUtils {
private static void register() {
if (!registrationDone) {
if (securityProvider == null && (registerBouncyCastle == null || registerBouncyCastle)) {
registerSecurityProvider("org.bouncycastle.jce.provider.BouncyCastleProvider");
if (securityProvider == null && registerBouncyCastle == null) {
LOG.info("BouncyCastle not registered, using the default JCE provider");
} else if (securityProvider == null) {
LOG.error("Failed to register BouncyCastle as the defaut JCE provider");
throw new SSHRuntimeException("Failed to register BouncyCastle as the defaut JCE provider");
if (securityProvider == null && (registerBouncyCastle == null || registerBouncyCastle))
// Use an inner class to avoid a strong dependency on BouncyCastle
try {
new BouncyCastleRegistration().run();
} catch (Throwable t) {
if (registerBouncyCastle == null)
LOG.info("BouncyCastle not registered, using the default JCE provider");
else {
LOG.error("Failed to register BouncyCastle as the defaut JCE provider");
throw new SSHRuntimeException("Failed to register BouncyCastle as the defaut JCE provider", t);
}
}
}
registrationDone = true;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More