mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
Compare commits
350 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6213401db | ||
|
|
19ec6d9d8d | ||
|
|
0ba491c01a | ||
|
|
73d7560e6e | ||
|
|
0e0d730bbf | ||
|
|
6becee176a | ||
|
|
4b1619d54f | ||
|
|
64f448d438 | ||
|
|
a5efdf1f0d | ||
|
|
588853554a | ||
|
|
7bde5c15c1 | ||
|
|
3c85b86915 | ||
|
|
2ca0fa4732 | ||
|
|
769c896e53 | ||
|
|
eb19325bc6 | ||
|
|
2d8af5a687 | ||
|
|
c4fef33d8f | ||
|
|
ff85e832af | ||
|
|
0dcb4b9a7a | ||
|
|
2baf51bf64 | ||
|
|
3194fd9bd0 | ||
|
|
ab3f0143bd | ||
|
|
9671352bda | ||
|
|
91105e6a07 | ||
|
|
4e802cec86 | ||
|
|
dfdc464e08 | ||
|
|
fa7c40cc66 | ||
|
|
b1be9258b4 | ||
|
|
11543b2c00 | ||
|
|
3526694558 | ||
|
|
d618156ede | ||
|
|
98063680bc | ||
|
|
17754a65fe | ||
|
|
2bb52fcf7d | ||
|
|
1a70023e2d | ||
|
|
5e25c017bf | ||
|
|
27a5039831 | ||
|
|
c2d25a9d62 | ||
|
|
2a22809de2 | ||
|
|
9d1f6d9d83 | ||
|
|
4542d94440 | ||
|
|
46a0cbac9e | ||
|
|
f470ddf219 | ||
|
|
d09276fe01 | ||
|
|
241c355e20 | ||
|
|
56ef6c1223 | ||
|
|
989fb8cde6 | ||
|
|
d10a33ec59 | ||
|
|
327a4c4c5b | ||
|
|
d5c045defd | ||
|
|
02b70ef427 | ||
|
|
fdf08ef3c9 | ||
|
|
633b42fec8 | ||
|
|
3c594d9a1c | ||
|
|
c2b9c0266d | ||
|
|
0e784dd171 | ||
|
|
f322a4b060 | ||
|
|
0cd19284ee | ||
|
|
a5017d55c8 | ||
|
|
2f7b181306 | ||
|
|
20223d3614 | ||
|
|
cac340dd43 | ||
|
|
00cd335f47 | ||
|
|
e14fb2f695 | ||
|
|
b0dee02bf9 | ||
|
|
17c09eb471 | ||
|
|
0301d4537f | ||
|
|
f71d34e106 | ||
|
|
254f739ac1 | ||
|
|
aa201fa08c | ||
|
|
8721269d0f | ||
|
|
971ccf6273 | ||
|
|
813469646e | ||
|
|
17c368f9c2 | ||
|
|
4de9f8ab9f | ||
|
|
deff097170 | ||
|
|
7556a7f6f6 | ||
|
|
c5792fe4a8 | ||
|
|
02cfeb9a6a | ||
|
|
5e771382fe | ||
|
|
59e68f1ed7 | ||
|
|
7d07c1bb46 | ||
|
|
5bebe044aa | ||
|
|
d2a16385da | ||
|
|
adc0451b3f | ||
|
|
df5e73f1e8 | ||
|
|
eeeba57c73 | ||
|
|
db48ff85c0 | ||
|
|
49a450fb53 | ||
|
|
80d93ae8e7 | ||
|
|
42c52e4fe6 | ||
|
|
329966ecc4 | ||
|
|
10918f3201 | ||
|
|
b5f0d4c9fb | ||
|
|
c10cb7f138 | ||
|
|
81e26f4a7f | ||
|
|
aa53effce8 | ||
|
|
76e6e572b4 | ||
|
|
2003a9f8c9 | ||
|
|
84a7677a62 | ||
|
|
3bcd3530cf | ||
|
|
a63f9ee8fd | ||
|
|
4be5a98ea3 | ||
|
|
26df2f3c23 | ||
|
|
39b72eed62 | ||
|
|
d55eb6d02e | ||
|
|
265e9d2916 | ||
|
|
0b6552654b | ||
|
|
dabe43dfdc | ||
|
|
0f67fa2541 | ||
|
|
54018a4a81 | ||
|
|
ca81c2eea4 | ||
|
|
048f84b42a | ||
|
|
8ca6451d5d | ||
|
|
5e1be8b1b0 | ||
|
|
bc4da2ea8e | ||
|
|
09fb2b9dc2 | ||
|
|
4045d5a7ef | ||
|
|
d0daa2c12f | ||
|
|
64a2a4f779 | ||
|
|
7cb1f8b11c | ||
|
|
73bc785ab4 | ||
|
|
9d697ede12 | ||
|
|
2b62492caf | ||
|
|
a0f1aa7e2c | ||
|
|
0e981f7656 | ||
|
|
a014567c9e | ||
|
|
8454cf1a0c | ||
|
|
663f118d0f | ||
|
|
47d73a9381 | ||
|
|
c4552d5f3d | ||
|
|
7a884d0938 | ||
|
|
661f63eab7 | ||
|
|
a71a7d7d33 | ||
|
|
d2e0f50d0c | ||
|
|
b41f0acd19 | ||
|
|
a1f501a027 | ||
|
|
fef9cfaf79 | ||
|
|
c67ae242f2 | ||
|
|
823f1e5759 | ||
|
|
f046a41750 | ||
|
|
c161fe26f6 | ||
|
|
ec46a7a489 | ||
|
|
762d088388 | ||
|
|
99c85672b8 | ||
|
|
28d57840ab | ||
|
|
2984291d84 | ||
|
|
bdbd9d7eb5 | ||
|
|
9ac55de26c | ||
|
|
a9928c2882 | ||
|
|
c6c9a3f6a8 | ||
|
|
0918bc626f | ||
|
|
aa7748395d | ||
|
|
cf077e2a4f | ||
|
|
c58c7c7c60 | ||
|
|
0b548d9d13 | ||
|
|
eb1629f250 | ||
|
|
8856aaea61 | ||
|
|
1f6615b57a | ||
|
|
a96fbfcf2f | ||
|
|
e5084ed8db | ||
|
|
3729119e23 | ||
|
|
aed3decf1d | ||
|
|
303c03061c | ||
|
|
15e6924fc4 | ||
|
|
9e8bef24c5 | ||
|
|
5e3a08a637 | ||
|
|
d0800058e8 | ||
|
|
ad9c2d5411 | ||
|
|
ed65176b68 | ||
|
|
28f3280a84 | ||
|
|
d69f722908 | ||
|
|
1d7cb8c2c6 | ||
|
|
6ad6242ed1 | ||
|
|
3310530d42 | ||
|
|
3685f9dc36 | ||
|
|
f8cad120a6 | ||
|
|
56dd4e4af4 | ||
|
|
9f8cf1f298 | ||
|
|
a51270791d | ||
|
|
d43fc4551e | ||
|
|
93bf6c0089 | ||
|
|
7b535a8db3 | ||
|
|
9d4f8fc46a | ||
|
|
2b21ec6032 | ||
|
|
8e15a8bd7d | ||
|
|
531eb97767 | ||
|
|
e36fd0fb3d | ||
|
|
382321deca | ||
|
|
7b75fb3d53 | ||
|
|
4d84d3f67c | ||
|
|
8eb7d1a2ad | ||
|
|
a03fa9ac63 | ||
|
|
bcb15e6ccd | ||
|
|
d85b22fe8d | ||
|
|
f4b71941a3 | ||
|
|
636f896850 | ||
|
|
56c0baf814 | ||
|
|
edfb069f2a | ||
|
|
65b3003e72 | ||
|
|
fbee0b3956 | ||
|
|
fd60139b98 | ||
|
|
0b397bc3d7 | ||
|
|
40f956b4b6 | ||
|
|
ef3f7a2eaf | ||
|
|
8134113510 | ||
|
|
c883c87963 | ||
|
|
920537dac9 | ||
|
|
356ec9ed08 | ||
|
|
aa47b0c5f7 | ||
|
|
d3ed3cfe0f | ||
|
|
786734ce26 | ||
|
|
9cb5bf4e10 | ||
|
|
0e3f7c2bbf | ||
|
|
66d4b34eba | ||
|
|
aafb9942a3 | ||
|
|
d1dff550ce | ||
|
|
ac2720becd | ||
|
|
48dd1fdc41 | ||
|
|
9826a71d2b | ||
|
|
936eb26e9e | ||
|
|
9438157b93 | ||
|
|
7d326e5ae4 | ||
|
|
f038b5ce2b | ||
|
|
20879a4aa5 | ||
|
|
516abb0282 | ||
|
|
0ad51709c2 | ||
|
|
c9c68f019e | ||
|
|
fc75f9796c | ||
|
|
61af500c3e | ||
|
|
56553ea086 | ||
|
|
86e6631b1e | ||
|
|
b6f437a932 | ||
|
|
9e3b9f7c24 | ||
|
|
766ab916ee | ||
|
|
cdca43a848 | ||
|
|
3ce7c2ebfb | ||
|
|
ca4e0bf2d7 | ||
|
|
2ca2bbd633 | ||
|
|
256e65dea4 | ||
|
|
1feb7fe9a6 | ||
|
|
d95b4db930 | ||
|
|
677f482a69 | ||
|
|
179b30ef4e | ||
|
|
f59bbccc5f | ||
|
|
bf34072c3a | ||
|
|
771751ca4c | ||
|
|
968d4284a0 | ||
|
|
63927a3e2b | ||
|
|
ac262f8086 | ||
|
|
6e56cd9d0a | ||
|
|
2f6025d9ba | ||
|
|
275e98e55b | ||
|
|
655d070571 | ||
|
|
c9775ca2c7 | ||
|
|
a2fb4fbd98 | ||
|
|
6185ac4db8 | ||
|
|
e420593fa9 | ||
|
|
68b924863e | ||
|
|
613ace1864 | ||
|
|
78e0ecd264 | ||
|
|
64085e62f4 | ||
|
|
8c7d2fa8d0 | ||
|
|
766d292bad | ||
|
|
a40957fffc | ||
|
|
8ffd852e67 | ||
|
|
b90be512e7 | ||
|
|
c0d49cf6b3 | ||
|
|
1b5b2b25b7 | ||
|
|
1dad19ca6e | ||
|
|
90fa26925d | ||
|
|
9425300262 | ||
|
|
f2bfe9bfcf | ||
|
|
71498ad961 | ||
|
|
7b8b1cfdf5 | ||
|
|
3f29879eca | ||
|
|
79c1ae2bb0 | ||
|
|
819d411cf1 | ||
|
|
6579f6f710 | ||
|
|
cf5830eda5 | ||
|
|
36ad389ccf | ||
|
|
f63a88ec9f | ||
|
|
7379a89268 | ||
|
|
219901211e | ||
|
|
8c1329036a | ||
|
|
733c19350c | ||
|
|
e5ec84c06a | ||
|
|
ed0156c985 | ||
|
|
6321685881 | ||
|
|
f6b4d47945 | ||
|
|
d198ef121c | ||
|
|
7786468875 | ||
|
|
0847e8460a | ||
|
|
62b8726807 | ||
|
|
a6af27ae91 | ||
|
|
628cbf5eba | ||
|
|
e134e00574 | ||
|
|
1caa7ac722 | ||
|
|
4183776adb | ||
|
|
791f112752 | ||
|
|
233f3765c9 | ||
|
|
5f292d398f | ||
|
|
ba347f927d | ||
|
|
6f9ecf69e4 | ||
|
|
e78ae4dbeb | ||
|
|
618f2fd111 | ||
|
|
8503046302 | ||
|
|
c6cde27e4b | ||
|
|
113aa0aebd | ||
|
|
e7c50165c7 | ||
|
|
09616c4834 | ||
|
|
df710d8dc9 | ||
|
|
df82774ea3 | ||
|
|
caa6cca665 | ||
|
|
9a5ccefb5d | ||
|
|
90f8c592b0 | ||
|
|
f491e8d101 | ||
|
|
77c10334f1 | ||
|
|
0edc4a5787 | ||
|
|
b43cff07bf | ||
|
|
1ab72b7eaf | ||
|
|
3229584a95 | ||
|
|
364a82154d | ||
|
|
11fbf2964b | ||
|
|
a248d50301 | ||
|
|
fddc943565 | ||
|
|
ae834134d0 | ||
|
|
bc41908694 | ||
|
|
bf1a855647 | ||
|
|
cd3b0a5bd6 | ||
|
|
b01eccda4a | ||
|
|
4c9ebc306d | ||
|
|
c3f75cda19 | ||
|
|
1f0e2b1e69 | ||
|
|
8e55e50fd9 | ||
|
|
eb8b7b51ca | ||
|
|
a2cccd5cef | ||
|
|
50403483da | ||
|
|
3c230a0fc4 | ||
|
|
4f152749ce | ||
|
|
e0df6a5fb5 | ||
|
|
f36c011844 | ||
|
|
94113eb6f5 | ||
|
|
0532f27a78 | ||
|
|
bd67135ffa | ||
|
|
ca49ca324f | ||
|
|
ac2ffbc367 | ||
|
|
dbb0eb0238 | ||
|
|
347e6ad655 | ||
|
|
2622833831 |
8
.bettercodehub.yml
Normal file
8
.bettercodehub.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
exclude:
|
||||
- /build-publishing.gradle
|
||||
- /build.gradle
|
||||
- /settings.gradle
|
||||
component_depth: 1
|
||||
languages:
|
||||
- groovy
|
||||
- java
|
||||
2
.github/CODEOWNERS
vendored
Normal file
2
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
* @hierynomus
|
||||
|
||||
55
.github/workflows/gradle.yml
vendored
Normal file
55
.github/workflows/gradle.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# 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:
|
||||
java12:
|
||||
name: Build with Java 12
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 12
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 12
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew check
|
||||
# java10:
|
||||
# name: Build with Java 10
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: Set up JDK 10
|
||||
# uses: actions/setup-java@v1
|
||||
# with:
|
||||
# java-version: 10
|
||||
# - name: Grant execute permission for gradlew
|
||||
# run: chmod +x gradlew
|
||||
# - name: Build with Gradle
|
||||
# run: ./gradlew check -xanimalsnifferMain -xanimalsnifferTest
|
||||
|
||||
integration:
|
||||
name: Integration test
|
||||
needs: [java12]
|
||||
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: 12
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew integrationTest
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -10,8 +10,14 @@
|
||||
.settings/
|
||||
|
||||
# Output dirs
|
||||
out/
|
||||
target/
|
||||
classes/
|
||||
bin/
|
||||
build/
|
||||
docs/
|
||||
.gradle/
|
||||
sshj.jar
|
||||
|
||||
|
||||
# MacOS X
|
||||
.DS_Store
|
||||
|
||||
1
.java-version
Normal file
1
.java-version
Normal file
@@ -0,0 +1 @@
|
||||
11.0
|
||||
@@ -1,2 +0,0 @@
|
||||
language: java
|
||||
sudo: false
|
||||
13
LICENSE_HEADER
Normal file
13
LICENSE_HEADER
Normal file
@@ -0,0 +1,13 @@
|
||||
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
2
NOTICE
@@ -15,7 +15,7 @@ The Apache Software Foundation (http://www.apache.org/):
|
||||
== in this case for the SSHD distribution. ==
|
||||
=========================================================================
|
||||
|
||||
This product contains software developped by JCraft,Inc. and subject to
|
||||
This product contains software developed by JCraft,Inc. and subject to
|
||||
the following license:
|
||||
|
||||
Copyright (c) 2002,2003,2004,2005,2006,2007,2008 Atsuhiko Yamanaka, JCraft,Inc.
|
||||
|
||||
116
README.adoc
116
README.adoc
@@ -1,10 +1,15 @@
|
||||
= sshj - SSHv2 library for Java
|
||||
Jeroen van Erp
|
||||
:sshj_groupid: com.hierynomus
|
||||
:sshj_version: 0.15.0
|
||||
:sshj_version: 0.30.0
|
||||
:source-highlighter: pygments
|
||||
|
||||
image::https://travis-ci.org/hierynomus/sshj.svg?branch=master[]
|
||||
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"]
|
||||
|
||||
To get started, have a look at one of the examples. Hopefully you will find the API pleasant to work with :)
|
||||
|
||||
@@ -34,7 +39,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 Overthere repository.
|
||||
. Clone the SSHJ 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`.
|
||||
|
||||
@@ -63,20 +68,27 @@ ciphers::
|
||||
SSHJ also supports the following extended (non official) ciphers: `camellia{128,192,256}-{cbc,ctr}`, `camellia{128,192,256}-{cbc,ctr}@openssh.org`
|
||||
|
||||
key exchange::
|
||||
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
|
||||
`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`
|
||||
|
||||
signatures::
|
||||
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ssh-ed25519
|
||||
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`, `ssh-rsa2-256`, `ssh-rsa2-512`
|
||||
|
||||
mac::
|
||||
`hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`
|
||||
`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`
|
||||
|
||||
compression::
|
||||
`zlib` and `zlib@openssh.com` (delayed zlib)
|
||||
|
||||
private key files::
|
||||
`pkcs8` encoded (what openssh uses)
|
||||
`pkcs5`, `pkcs8`, `openssh-key-v1`, `ssh-rsa-cert-v01@openssh.com`, `ssh-dsa-cert-v01@openssh.com`
|
||||
|
||||
If you need something that is not included, it shouldn't be too hard to add (do contribute it!)
|
||||
|
||||
@@ -89,13 +101,97 @@ 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.30.0 (2020-??-??)::
|
||||
* **BREAKING CHANGE**: Removed `setSignatureFactories` and `getSignatureFactories` from the Config and switched them for `getKeyAlgorithms` and `setKeyAlgorithms`
|
||||
* Fixed https://github.com/hierynomus/sshj/pulls/588[#588]: Add support for `ssh-rsa2-256` and `ssh-rsa2-512` signatures
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/579[#579]: Fix NPE in OpenSSHKnownHosts
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/587[#587]: Add passwordfinder retry for OpenSSHKeyV1KeyFile
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/586[#586]: Make KeyType compatible with Android Store
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/593[#593]: Change `UserAuth.getAllowedMethods()` to Collection return type
|
||||
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
|
||||
|
||||
@@ -17,7 +17,7 @@ configurations {
|
||||
pom
|
||||
}
|
||||
|
||||
def bouncycastleVersion = "1.50"
|
||||
def bouncycastleVersion = "1.66"
|
||||
|
||||
dependencies {
|
||||
compile "org.slf4j:slf4j-api:1.7.7"
|
||||
|
||||
385
build.gradle
385
build.gradle
@@ -1,30 +1,164 @@
|
||||
apply plugin: "java"
|
||||
apply plugin: "maven"
|
||||
apply plugin: "signing"
|
||||
apply plugin: "osgi"
|
||||
import java.text.SimpleDateFormat
|
||||
import com.bmuschko.gradle.docker.tasks.container.*
|
||||
import com.bmuschko.gradle.docker.tasks.image.*
|
||||
|
||||
group = "com.hierynomus"
|
||||
version = "0.15.0"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
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 "6.4.0"
|
||||
id "com.github.hierynomus.license" version "0.12.1"
|
||||
id "com.jfrog.bintray" version "1.8.5"
|
||||
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'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
group = "com.hierynomus"
|
||||
|
||||
configurations {
|
||||
compile {
|
||||
transitive = false
|
||||
scmVersion {
|
||||
tag {
|
||||
prefix = 'v'
|
||||
versionSeparator = ''
|
||||
}
|
||||
hooks {
|
||||
pre 'fileUpdate', [file: 'README.adoc', pattern: { v, c -> /:sshj_version: .*/}, replacement: { v, c -> ":sshj_version: $v" }]
|
||||
pre 'commit'
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
project.version = scmVersion.version
|
||||
|
||||
defaultTasks "build"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations.compile.transitive = false
|
||||
|
||||
def bouncycastleVersion = "1.66"
|
||||
def sshdVersion = "2.1.0"
|
||||
|
||||
dependencies {
|
||||
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 "com.hierynomus:asn-one:0.4.0"
|
||||
|
||||
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'])
|
||||
}
|
||||
|
||||
if (!JavaVersion.current().isJava9Compatible()) {
|
||||
throw new GradleScriptException("Minimum compilation version is Java 9")
|
||||
}
|
||||
|
||||
// This disables the pedantic doclint feature of JDK8
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
compileJava {
|
||||
options.compilerArgs.addAll(['--release', '7'])
|
||||
}
|
||||
|
||||
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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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')
|
||||
}
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
testClassesDirs = sourceSets.integrationTest.output.classesDirs
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
testLogging {
|
||||
exceptionFormat = 'full'
|
||||
}
|
||||
include "**/*Test.*"
|
||||
include "**/*Spec.*"
|
||||
if (!project.hasProperty("allTests")) {
|
||||
useJUnit {
|
||||
excludeCategories 'com.hierynomus.sshj.test.SlowTests'
|
||||
@@ -43,131 +177,118 @@ test {
|
||||
}
|
||||
}
|
||||
|
||||
def bouncycastleVersion = "1.51"
|
||||
project.tasks.compileGroovy.onlyIf { false }
|
||||
|
||||
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"
|
||||
|
||||
compile "net.vrallev.ecc:ecc-25519-java:1.0.1"
|
||||
|
||||
testCompile "junit:junit:4.11"
|
||||
testCompile "org.mockito:mockito-core:1.9.5"
|
||||
testCompile "org.apache.sshd:sshd-core:1.0.0"
|
||||
testRuntime "ch.qos.logback:logback-classic:1.1.2"
|
||||
github {
|
||||
user 'hierynomus'
|
||||
license 'Apache'
|
||||
}
|
||||
|
||||
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.*"
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
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")
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
mavenCentralSync {
|
||||
sync = true
|
||||
user = project.property("sonatypeUsername")
|
||||
password = project.property("sonatypePassword")
|
||||
close = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jacocoTestReport {
|
||||
reports {
|
||||
xml.enabled true
|
||||
html.enabled true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task buildItestImage(type: DockerBuildImage) {
|
||||
inputDir = file('src/itest/docker-image')
|
||||
images.add('sshj/sshd-itest:latest')
|
||||
}
|
||||
|
||||
task createItestContainer(type: DockerCreateContainer) {
|
||||
dependsOn buildItestImage
|
||||
targetImageId buildItestImage.getImageId()
|
||||
hostConfig.portBindings = ['2222:22']
|
||||
hostConfig.autoRemove = true
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<groupId>com.hierynomus</groupId>
|
||||
<artifactId>sshj-examples</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.14.0</version>
|
||||
<version>0.19.1</version>
|
||||
|
||||
<name>sshj-examples</name>
|
||||
<description>Examples for SSHv2 library for Java</description>
|
||||
@@ -55,7 +55,7 @@
|
||||
<dependency>
|
||||
<groupId>com.hierynomus</groupId>
|
||||
<artifactId>sshj</artifactId>
|
||||
<version>0.15.0</version>
|
||||
<version>0.24.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -20,30 +5,36 @@ 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"));
|
||||
final Session session = ssh.startSession();
|
||||
try {
|
||||
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();
|
||||
}
|
||||
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 {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
50
examples/src/main/java/net/schmizz/sshj/examples/Jump.java
Normal file
50
examples/src/main/java/net/schmizz/sshj/examples/Jump.java
Normal file
@@ -0,0 +1,50 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,13 @@
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -24,6 +9,7 @@ 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 {
|
||||
@@ -48,18 +34,18 @@ class RudimentaryPTY {
|
||||
|
||||
final Shell shell = session.startShell();
|
||||
|
||||
new StreamCopier(shell.getInputStream(), System.out)
|
||||
new StreamCopier(shell.getInputStream(), System.out, LoggerFactory.DEFAULT)
|
||||
.bufSize(shell.getLocalMaxPacketSize())
|
||||
.spawn("stdout");
|
||||
|
||||
new StreamCopier(shell.getErrorStream(), System.err)
|
||||
new StreamCopier(shell.getErrorStream(), System.err, LoggerFactory.DEFAULT)
|
||||
.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())
|
||||
new StreamCopier(System.in, shell.getOutputStream(), LoggerFactory.DEFAULT)
|
||||
.bufSize(shell.getRemoteMaxPacketSize())
|
||||
.copy();
|
||||
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -37,4 +22,4 @@ public class SCPDownload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -42,4 +27,4 @@ public class SCPUpload {
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -42,4 +27,4 @@ public class SFTPDownload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -44,4 +29,4 @@ public class SFTPUpload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -20,6 +5,7 @@ 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;
|
||||
@@ -57,8 +43,8 @@ public class X11 {
|
||||
|
||||
final Command cmd = sess.exec("/usr/X11/bin/xcalc");
|
||||
|
||||
new StreamCopier(cmd.getInputStream(), System.out).spawn("stdout");
|
||||
new StreamCopier(cmd.getErrorStream(), System.err).spawn("stderr");
|
||||
new StreamCopier(cmd.getInputStream(), System.out, LoggerFactory.DEFAULT).spawn("stdout");
|
||||
new StreamCopier(cmd.getErrorStream(), System.err, LoggerFactory.DEFAULT).spawn("stderr");
|
||||
|
||||
// Wait for session & X11 channel to get closed
|
||||
ssh.getConnection().join();
|
||||
@@ -67,4 +53,4 @@ public class X11 {
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
||||
#Wed Nov 04 09:47:51 CET 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip
|
||||
|
||||
147
gradlew
vendored
147
gradlew
vendored
@@ -1,4 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -6,47 +22,6 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# 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"
|
||||
@@ -61,9 +36,49 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
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='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# 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
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@@ -90,7 +105,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
@@ -110,10 +125,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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`
|
||||
@@ -138,27 +154,30 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# 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"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
33
gradlew.bat
vendored
33
gradlew.bat
vendored
@@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@@ -8,14 +24,17 @@
|
||||
@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 Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@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="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
@@ -46,10 +65,9 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
@rem Get command-line arguments, handling Windows 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.
|
||||
@@ -60,11 +78,6 @@ 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
|
||||
|
||||
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = "sshj"
|
||||
24
src/itest/docker-image/Dockerfile
Normal file
24
src/itest/docker-image/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
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
|
||||
ADD test-container/users_rsa_ca.pub /etc/ssh/users_rsa_ca.pub
|
||||
|
||||
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", "-o", "LogLevel=DEBUG2"]
|
||||
9
src/itest/docker-image/authorized_keys
Normal file
9
src/itest/docker-image/authorized_keys
Normal file
@@ -0,0 +1,9 @@
|
||||
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
|
||||
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMvfRYSe44VQGwxexOMibcM3+fWeUP1jrBofOxFDRRrzRF8dK/vll2svqTPXMRnITnT1UoemEcB5OHtvH4hzfh/HFeDxJ5S7UncYxoClTSa8MeMFG2Zj9CoUZs1SHbwSGg== root@sshj
|
||||
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHquUYgkU9wJrcxDWVtdqtfqf6SBDdPDRxwDl7OCohV2UNu2KdjJwSj8j0fsPeMdHjSiv9OCnHYrVilQ+W5WW5q5wGXwk10oIcV0JJscohLA0nS7mKinBrxUwVHnNZbPExFciicnEArcYRb1BuT7HF8hfjuSSpWS0rob6kloSSi/jV7ZA== root@sshj
|
||||
5
src/itest/docker-image/test-container/ssh_host_ecdsa_key
Normal file
5
src/itest/docker-image/test-container/ssh_host_ecdsa_key
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOpOBFjqe0hjK/hs4WZ3dZqnzanq1L3/JbvV1TCkbe4ToAoGCCqGSM49
|
||||
AwEHoUQDQgAEVzkrS7Yj0nXML7A3mE08YDthfBR/ZbyYJDIq1vTzcqs6KTaCT529
|
||||
swNXWLHO+mbHviZcRiI57ULXHZ1emom/Jw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFc5K0u2I9J1zC+wN5hNPGA7YXwUf2W8mCQyKtb083KrOik2gk+dvbMDV1ixzvpmx74mXEYiOe1C1x2dXpqJvyc= root@404b27be2bf4
|
||||
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBFG9PKAq8FtH0me+LHUE6YaVANCMqy/Znkffzief1W/gAAAKCyyoBkssqA
|
||||
ZAAAAAtzc2gtZWQyNTUxOQAAACBFG9PKAq8FtH0me+LHUE6YaVANCMqy/Znkffzief1W/g
|
||||
AAAED+Yfza2xk5LqP9pN6TpvhWYP0L60zOQJpHhbEuiS3LLkUb08oCrwW0fSZ74sdQTphp
|
||||
UA0IyrL9meR9/OJ5/Vb+AAAAF2FqdmFuZXJwQEhlaW1kYWxsLmxvY2FsAQIDBAUG
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEUb08oCrwW0fSZ74sdQTphpUA0IyrL9meR9/OJ5/Vb+ ajvanerp@Heimdall.local
|
||||
134
src/itest/docker-image/test-container/sshd_config
Normal file
134
src/itest/docker-image/test-container/sshd_config
Normal file
@@ -0,0 +1,134 @@
|
||||
# $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
|
||||
|
||||
TrustedUserCAKeys /etc/ssh/users_rsa_ca.pub
|
||||
1
src/itest/docker-image/test-container/users_rsa_ca.pub
Normal file
1
src/itest/docker-image/test-container/users_rsa_ca.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDN70b/cYHZQMD1YW0mlncXqC2l++sEWrVYlIUCzNxNhRYjI4UmEVEq3ru1h6K3ZVAJi1DcZuf5ne1ZXtwJ1Uw1JA4wGdKw+9TwAb5Gubn+VEowgt62kLAPeChiPucTXD0FDDhIUOBv3KxytdrJIYAtzZT27STsBiDF1+7Ld3wk/1Dg9NAaI6q40PmuicTEACQRHn5snI1t9+LgZTd3/PPE5pjJM0ow9+r6mlUUM5oHCk5sZ8DBuRR1Ram4sxp/LFQM+9feMmW3ZM2C5AN0JG4A7NXnlwiTKmNVrGI0iFucBBKhjxN1qdgBF11/42cCrerC9UW1auTTi9mqwEIqBGL30VOPy+dCPQQViP+C09CBgyr3wpZciPKP1mvmcOkC5FDzKg9e3v1JBq0fqZgwt+PPG8cGnxRCGEQ+ZMLDuAixkQUEwDWeMskHLkbjUEiVZydViCPSzFczGtKatQiQVZA5Zx0Gn2sUaQjykhWzqKNL8oIbolEdkH9ubOZWNi0brzU= root@sshj
|
||||
6
src/itest/generate.sh
Normal file
6
src/itest/generate.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Don't call it frequently. It's rather a documentation how everything is generated.
|
||||
ssh-keygen -f resources/users_rsa_ca -t rsa -N ''
|
||||
mv resources/users_rsa_ca.pub docker-image/test-container
|
||||
ssh-keygen -f resources/keyfiles/id_rsa2 -t rsa -m pem -N ''
|
||||
ssh-keygen -s resources/users_rsa_ca -I my_key_id -n sshj resources/keyfiles/id_rsa2.pub
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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())
|
||||
}
|
||||
|
||||
}
|
||||
95
src/itest/groovy/com/hierynomus/sshj/IntegrationSpec.groovy
Normal file
95
src/itest/groovy/com/hierynomus/sshj/IntegrationSpec.groovy
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.key.KeyAlgorithms
|
||||
import net.schmizz.sshj.DefaultConfig
|
||||
import net.schmizz.sshj.SSHClient
|
||||
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.setKeyAlgorithms(Collections.singletonList(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 << [KeyAlgorithms.ECDSASHANistp256(), KeyAlgorithms.EdDSA25519()]
|
||||
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
|
||||
"id_ecdsa_nistp384_opensshv1" | null
|
||||
"id_ecdsa_nistp521_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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 com.hierynomus.sshj.IntegrationBaseSpec
|
||||
import net.schmizz.sshj.DefaultConfig
|
||||
import spock.lang.Unroll
|
||||
|
||||
class RsaSignatureClientKeySpec extends IntegrationBaseSpec {
|
||||
@Unroll
|
||||
def "should correctly connect using publickey auth with RSA key with signature"() {
|
||||
given:
|
||||
def client = getConnectedClient(new DefaultConfig())
|
||||
|
||||
when:
|
||||
client.authPublickey(USERNAME, "src/itest/resources/keyfiles/id_rsa2")
|
||||
|
||||
then:
|
||||
client.authenticated
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 com.hierynomus.sshj.IntegrationBaseSpec
|
||||
import com.hierynomus.sshj.key.KeyAlgorithms
|
||||
import net.schmizz.sshj.DefaultConfig
|
||||
import spock.lang.Unroll
|
||||
|
||||
class SignatureSpec extends IntegrationBaseSpec {
|
||||
|
||||
@Unroll
|
||||
def "should correctly connect with #sig Signature"() {
|
||||
given:
|
||||
def cfg = new DefaultConfig()
|
||||
cfg.setKeyAlgorithms(Collections.singletonList(sigFactory))
|
||||
def client = getConnectedClient(cfg)
|
||||
|
||||
when:
|
||||
client.authPublickey(USERNAME, KEYFILE)
|
||||
|
||||
then:
|
||||
client.authenticated
|
||||
|
||||
where:
|
||||
sigFactory << [KeyAlgorithms.SSHRSA(), KeyAlgorithms.RSASHA256(), KeyAlgorithms.RSASHA512()]
|
||||
sig = sigFactory.name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 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
|
||||
}
|
||||
}
|
||||
5
src/itest/resources/keyfiles/id_ecdsa_nistp256
Normal file
5
src/itest/resources/keyfiles/id_ecdsa_nistp256
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJUMlsSlXqCZmCjlN4kV7hzP+p9pu0fwJ8r4m1qle58SoAoGCCqGSM49
|
||||
AwEHoUQDQgAE4RBy+jCJXeKB1E7uso+tmtqjWEJCucLi2CzGpIl1AJsAEj68et1s
|
||||
lF9Zk25KTjxoC0BEnMlWaSf+vrcQ8mCSHw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
10
src/itest/resources/keyfiles/id_ecdsa_nistp384_opensshv1
Normal file
10
src/itest/resources/keyfiles/id_ecdsa_nistp384_opensshv1
Normal file
@@ -0,0 +1,10 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTL30WEnuOFUBsMXsTjIm3DN/n1nlD9
|
||||
Y6waHzsRQ0Ua80RfHSv75ZdrL6kz1zEZyE509VKHphHAeTh7bx+Ic34fxxXg8SeUu1J3GM
|
||||
aApU0mvDHjBRtmY/QqFGbNUh28EhoAAADYHWlHLx1pRy8AAAATZWNkc2Etc2hhMi1uaXN0
|
||||
cDM4NAAAAAhuaXN0cDM4NAAAAGEEy99FhJ7jhVAbDF7E4yJtwzf59Z5Q/WOsGh87EUNFGv
|
||||
NEXx0r++WXay+pM9cxGchOdPVSh6YRwHk4e28fiHN+H8cV4PEnlLtSdxjGgKVNJrwx4wUb
|
||||
ZmP0KhRmzVIdvBIaAAAAMQD3sx28SrtkuhN+Yu06BAoFLMMgneIqguM3jowaz0LWfP1Nhx
|
||||
Rnh9tNKM6YYvygCggAAAAPZmhlbm5la2VATGFwdG9w
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
12
src/itest/resources/keyfiles/id_ecdsa_nistp521_opensshv1
Normal file
12
src/itest/resources/keyfiles/id_ecdsa_nistp521_opensshv1
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQB6rlGIJFPcCa3MQ1lbXarX6n+kgQ3
|
||||
Tw0ccA5ezgqIVdlDbtinYycEo/I9H7D3jHR40or/Tgpx2K1YpUPluVluaucBl8JNdKCHFd
|
||||
CSbHKISwNJ0u5iopwa8VMFR5zWWzxMRXIonJxAK3GEW9Qbk+xxfIX47kkqVktK6G+pJaEk
|
||||
ov41e2QAAAEQwljQZcJY0GUAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
|
||||
AAAIUEAeq5RiCRT3AmtzENZW12q1+p/pIEN08NHHAOXs4KiFXZQ27Yp2MnBKPyPR+w94x0
|
||||
eNKK/04KcditWKVD5blZbmrnAZfCTXSghxXQkmxyiEsDSdLuYqKcGvFTBUec1ls8TEVyKJ
|
||||
ycQCtxhFvUG5PscXyF+O5JKlZLSuhvqSWhJKL+NXtkAAAAQVXt20tSeLzMU1U2nMv8CEEY
|
||||
Oyl1WIkGAcRatDBAfsE0+NcJ/eSbPXywWAqCzOElQ5ftNFz9t1kNXwW5qiLaaIBpAAAAD2
|
||||
ZoZW5uZWtlQExhcHRvcAECAwQ=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
9
src/itest/resources/keyfiles/id_ecdsa_opensshv1
Normal file
9
src/itest/resources/keyfiles/id_ecdsa_opensshv1
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR0ImZtMAW5iPIKIQPzfYq9TvnoIpC+
|
||||
kvRY2UvBh28eK0xyNVfr218cdjvWxVrXqdTxW+IqMLWZMX+oL0YxpC+jAAAAsD+6Oow/uj
|
||||
qMAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHQiZm0wBbmI8goh
|
||||
A/N9ir1O+egikL6S9FjZS8GHbx4rTHI1V+vbXxx2O9bFWtep1PFb4iowtZkxf6gvRjGkL6
|
||||
MAAAAgXNC11pInVAOd3xNphiHMoISeitf6h1IKbDM+niLrL5kAAAAXYWp2YW5lcnBASGVp
|
||||
bWRhbGwubG9jYWwB
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
7
src/itest/resources/keyfiles/id_ed25519_opensshv1
Normal file
7
src/itest/resources/keyfiles/id_ed25519_opensshv1
Normal file
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACAwHSYkZJATPMgvLHkxKAJ9j38Gyyq5HGoWdMcT6FiAiQAAAJDimgR84poE
|
||||
fAAAAAtzc2gtZWQyNTUxOQAAACAwHSYkZJATPMgvLHkxKAJ9j38Gyyq5HGoWdMcT6FiAiQ
|
||||
AAAECmsckQycWnfGQK6XtQpaMGODbAkMQOdJNK6XJSipB7dDAdJiRkkBM8yC8seTEoAn2P
|
||||
fwbLKrkcahZ0xxPoWICJAAAACXJvb3RAc3NoagECAwQ=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1,8 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABBLQVXV9f
|
||||
Wpw8AL9RTpAr//AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIJ8ww4hJG/gHJYdk
|
||||
jTTBDF1GNz+228nuWprPV+NbQauAAAAAoGHEO7x3fSRBohvrIR52U4XD3uqRnhrPYm01k1
|
||||
f4HHNNv46m92Zw6JKIB9Trrvp0sdMI8MVb79bN45rbn6mvpABtWl6T5TOTyMnKzDfAOx9c
|
||||
FTaasWFmgtgkXOsu5pLrYBAQgCHWbzjjz6KoV1DmD4SAn9Ojf9Oh+YdAEKZcsvklgpu+Kj
|
||||
nzN/DR0jt7Nzep2kNCLAS24QEkvQeATVSDiL8=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1,8 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB/aWL0WG
|
||||
iYPOTxGlFwvaCNAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOaWrwt3drIOjeBq
|
||||
2LSHRavxAT7ja2f+5soOUJl/zKSIAAAAsKplAiFbOhzcOJYFYBYm8sqYbvhPF8jKdQFkbo
|
||||
LAOeq+vQ0YBV9XUWQQM2tmL+RPjykPJZ2thcHLpVp3PfUEgo4bImCt939b3Ji3cEwD3QuK
|
||||
MIhjhx1KvSJNF/uhjwPJnttwHG+ld8F5Gv7LpTOUmOzXKGLIgYRuwonhs5ezdNv5ERs+Cq
|
||||
M9p/SW5ehL5KPJhGa5a+ZQXRojwEH7J4Q5xztH1gviTdIEpFWWQBH8rX6y
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
27
src/itest/resources/keyfiles/id_rsa
Normal file
27
src/itest/resources/keyfiles/id_rsa
Normal file
@@ -0,0 +1,27 @@
|
||||
-----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-----
|
||||
39
src/itest/resources/keyfiles/id_rsa2
Normal file
39
src/itest/resources/keyfiles/id_rsa2
Normal file
@@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG5QIBAAKCAYEA0MZ2xduy86/VbzZWnOnzSqUVeU7ajzwc3LF9vR9ZbufZdCB8
|
||||
pYRzpQ4B9v3umDZ3nX9qPM4f2iMVDfiz241SwmvV5s7WiOHPhy3ij5mUpRXOn3a8
|
||||
byVIjdraaVawL642p98cLKB9WKEjKaDw633aD7xzSIomqQboVZrMHNjvIanyd3U6
|
||||
j9mnoydXD1cIuceZx4S/Av8IQru9AiZYJ7rAfZwz3ip9YWcgT0yIohDbBSX7fsX2
|
||||
7KF6txIfRXJCJg0QO0kOYoMQmLYJtkVApwixdV29Vx2g5PBKXDQ12FwGXTnZG36v
|
||||
YYZ7ng12PV+xMyC1xPLdXnzrNR/lO4BGtT14GYJbwVM3gjBDrceavaayVW4SjFrq
|
||||
R5XDLjldKAfKtCHEavLv16Df1eAwnPlGAwmODlRqTHvL5oxBQibvNjDzVpvfqEsF
|
||||
RqP/d4AbYjARsKCkeu3PzUI+rq5AtwZ52XKgGdg13wURoAkIsNXonKo92avLnomq
|
||||
skdTYpfBEOUMSZO9AgMBAAECggGAadURhH84mft6kKPVCDo4UJCa8CGe/ZkVcHKx
|
||||
MNvhdC0nuIx3Y1hfXz5YlKJo/tQtkrNyYVyEHQpHtAts8VEUsOYFSrlzW3RMxVPn
|
||||
U7AhAAar9X41S4p02yQkL9339lOz9SlOmPjKUdFth77EIjxr/ColrpIJwwlzYWHV
|
||||
MpJttnz2IsRUaXOGXVil82rFS5f5RoDua1BpGZsd1yck7Q7oYUR7rpWPdX7XjBtZ
|
||||
7/3naRa2BK/J2m6JTKBtJcEj8zIPK4HXVO7NriQvhMyFAc5FRR+0ZQFp0bNdCELT
|
||||
k7nbDaHL8QPfzRiH9zLHe/WHJKNZxTcXctU1v/aBBNPAwsT4NHLydrtVagzBZ/YO
|
||||
ZBB1JKfpdmnQ54vNI1jlkNCbhkMNPZuDCCk3l4qq6JLi3DrYYqi1B8qzVxivw8ps
|
||||
0eNt4tMHqmOGwMBEzaYcAXfn66Lea84+QyGc5ibwPuBPtuQcNvHdY4BzXFerDqDI
|
||||
i/rdMH0ELvTPbgpgl3SrIqCWCoMpAoHBAPZcpWDK22owtw0D0QDylO/H3rkf3WX5
|
||||
5bo9FzoKtZdHNhZJUYFPBC26xHKXJgSKh6OuL9IlXtpQD3u4EctBevnJU8OZxKAM
|
||||
MJZ/vIXxnAGONuhcDs/kns0Bu9QNgdUOdYW1DomNaePQ669awhXtwaxVeBqwl6AT
|
||||
v6PnlzyRZK9Di/9xwkh/g0h4258ef0grD2oDUIxDvEnm9Ul9mE8MIqUjQw/dfpuA
|
||||
D2mW0nh+FK861VbGRrlumhr4y33KNIs5SwKBwQDY8WGyGlPvjPBUD4kHaledNCYu
|
||||
vMBvlo8UKlk9SpcRpHUqOm5IFmKmmLQdEqYip4PULGZVFjbrfil4LKV9pMxtmn56
|
||||
HKqteoWP1VuqhC1j2RdnX1KuIqB+sv30BkWsrOsOC6YwaDHl5eLPJv0BbFWApBEm
|
||||
/g2n2wpoHvGr2uSl0+B2mRw/BFcWw3zLcBB6OP/U4hjpPgEfwHLp2tG8DraT/dOm
|
||||
7o+DYQQz6ACqz8pzrMyzS/6uaR/YK70Q8RKPihcCgcEAliiH4EQkkkfY+oTN+h7h
|
||||
KnkPRpSmdEZpgCdGJelrHyaXT+QmWoNXz6ubmyCHWpM480ny+covUy8jEMxzhAiI
|
||||
NQFCHeF2V/q2DrUSqi1GYihVTTD3Ej2NkPSykCAfd0XV2cYucyaPWPz4+it+SrFc
|
||||
r3Z0uwfRkw8Waod4xcD0tmKcTPkAawHVefG4IvcKq2kbfwlAKg4LEJxF+yIjGGMU
|
||||
JsUkVeIyDgNy4W+9HxXx85APglFdwB4qra/hD+2UMxubAoHBAIRUeOtS8/AjYFVm
|
||||
RIepblgN/1xy9k8a35vFWTnxzcSNNIrVqX9/aB2G+Bbj0UNCOz+o9aLhMg7jnhgX
|
||||
47qIU8pnes6xvcqj+eSKmKeiiK1nNsdvddeSd6PROucnDEkQETE4Gd9dL1K0r2z8
|
||||
s0ey9VTKv0uxnFLPYcGxXmkd1GrymvC85GXsF9Ni2zSc3vAu5J7Oa7OahsT/dxj+
|
||||
yQCVWPlc00X4LsJM42tmEUIgDbYRqauUp31r0mjiBSnYYyH7cQKBwQC+2mw3oRsu
|
||||
La9Yj11WcwWy6in26JyITYmEnfwydDTdX8tn9XdPva94frC/TJkDmoh9gYSNZc8r
|
||||
zm9y/l9LpO98jIG+jH9wFRKO7xgCffZl4tbvu1DsGbh86IS7gvRbIwN5mnrKC61g
|
||||
4c/+PYAJnyC7+0oXhY2W7h2STUWi3/AvT/EnGLv7k41+9H3Hj5oqkWEt+DITgBia
|
||||
sTT3iRK6YVtXBg+AyG7nbobwTtZu98uFBjHwzGaelSPGGiWsUx4/u2Y=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
1
src/itest/resources/keyfiles/id_rsa2-cert.pub
Normal file
1
src/itest/resources/keyfiles/id_rsa2-cert.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgUsee85QZv49JUmGGA6cN852mR2cSsEst9KDH7gk3Lq4AAAADAQABAAABgQDQxnbF27Lzr9VvNlac6fNKpRV5TtqPPBzcsX29H1lu59l0IHylhHOlDgH2/e6YNnedf2o8zh/aIxUN+LPbjVLCa9XmztaI4c+HLeKPmZSlFc6fdrxvJUiN2tppVrAvrjan3xwsoH1YoSMpoPDrfdoPvHNIiiapBuhVmswc2O8hqfJ3dTqP2aejJ1cPVwi5x5nHhL8C/whCu70CJlgnusB9nDPeKn1hZyBPTIiiENsFJft+xfbsoXq3Eh9FckImDRA7SQ5igxCYtgm2RUCnCLF1Xb1XHaDk8EpcNDXYXAZdOdkbfq9hhnueDXY9X7EzILXE8t1efOs1H+U7gEa1PXgZglvBUzeCMEOtx5q9prJVbhKMWupHlcMuOV0oB8q0IcRq8u/XoN/V4DCc+UYDCY4OVGpMe8vmjEFCJu82MPNWm9+oSwVGo/93gBtiMBGwoKR67c/NQj6urkC3BnnZcqAZ2DXfBRGgCQiw1eicqj3Zq8ueiaqyR1Nil8EQ5QxJk70AAAAAAAAAAAAAAAEAAAAJbXlfa2V5X2lkAAAACAAAAARzc2hqAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQDN70b/cYHZQMD1YW0mlncXqC2l++sEWrVYlIUCzNxNhRYjI4UmEVEq3ru1h6K3ZVAJi1DcZuf5ne1ZXtwJ1Uw1JA4wGdKw+9TwAb5Gubn+VEowgt62kLAPeChiPucTXD0FDDhIUOBv3KxytdrJIYAtzZT27STsBiDF1+7Ld3wk/1Dg9NAaI6q40PmuicTEACQRHn5snI1t9+LgZTd3/PPE5pjJM0ow9+r6mlUUM5oHCk5sZ8DBuRR1Ram4sxp/LFQM+9feMmW3ZM2C5AN0JG4A7NXnlwiTKmNVrGI0iFucBBKhjxN1qdgBF11/42cCrerC9UW1auTTi9mqwEIqBGL30VOPy+dCPQQViP+C09CBgyr3wpZciPKP1mvmcOkC5FDzKg9e3v1JBq0fqZgwt+PPG8cGnxRCGEQ+ZMLDuAixkQUEwDWeMskHLkbjUEiVZydViCPSzFczGtKatQiQVZA5Zx0Gn2sUaQjykhWzqKNL8oIbolEdkH9ubOZWNi0brzUAAAGUAAAADHJzYS1zaGEyLTUxMgAAAYBxPe4yc3IwnjwULBv1tk3uTr35MKqIiDrIuWX9+7w/EJ9hQPjSZjtiOABP/C63F2c43zvN1XUqJ1Yvrh1dqpI5nIxexMLFRgJrawALHNsc5h5uLBL6q9rgyJsUNWXMgl9nOUGDDh+Jg6yM6SUVd44WuDTbgxtIwc5Uq6fE+HFowM35Xt0u9UEOBqOzpyBNYjNEsCMfPxkbzYGcLW9Y2C28ygrizRn+rhXFG3sQxraiCPVAL+d9NMGV3TaFXScEoCuXKRyHab1ch9g613FBL16k2rxZWoHfwI07bAUrpcv5upR5RMeeYrNmE7mrQ5WHemACd6QJtknPxOfxgAKOck486b29dgAt5C6P81T0mL0+52bu0LkbRYxVEExdeDurvhue2ZzGG11PbEJdLpVbgcPJr7dUkPPG2nPW4JLqqnzlulqu7Me07mgJuVK1OnXUKKziQ8BcDqx6lsdBg/CuKvL4PedFkSh32W+7VIQq7e9sVEV+Q5CngWfr2sYFh3cu3kw= lagunov@unit-1381
|
||||
1
src/itest/resources/keyfiles/id_rsa2.pub
Normal file
1
src/itest/resources/keyfiles/id_rsa2.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQxnbF27Lzr9VvNlac6fNKpRV5TtqPPBzcsX29H1lu59l0IHylhHOlDgH2/e6YNnedf2o8zh/aIxUN+LPbjVLCa9XmztaI4c+HLeKPmZSlFc6fdrxvJUiN2tppVrAvrjan3xwsoH1YoSMpoPDrfdoPvHNIiiapBuhVmswc2O8hqfJ3dTqP2aejJ1cPVwi5x5nHhL8C/whCu70CJlgnusB9nDPeKn1hZyBPTIiiENsFJft+xfbsoXq3Eh9FckImDRA7SQ5igxCYtgm2RUCnCLF1Xb1XHaDk8EpcNDXYXAZdOdkbfq9hhnueDXY9X7EzILXE8t1efOs1H+U7gEa1PXgZglvBUzeCMEOtx5q9prJVbhKMWupHlcMuOV0oB8q0IcRq8u/XoN/V4DCc+UYDCY4OVGpMe8vmjEFCJu82MPNWm9+oSwVGo/93gBtiMBGwoKR67c/NQj6urkC3BnnZcqAZ2DXfBRGgCQiw1eicqj3Zq8ueiaqyR1Nil8EQ5QxJk70= lagunov@unit-1381
|
||||
49
src/itest/resources/keyfiles/id_rsa_opensshv1
Normal file
49
src/itest/resources/keyfiles/id_rsa_opensshv1
Normal file
@@ -0,0 +1,49 @@
|
||||
-----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-----
|
||||
15
src/itest/resources/keyfiles/id_unknown_key
Normal file
15
src/itest/resources/keyfiles/id_unknown_key
Normal file
@@ -0,0 +1,15 @@
|
||||
-----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-----
|
||||
38
src/itest/resources/users_rsa_ca
Normal file
38
src/itest/resources/users_rsa_ca
Normal file
@@ -0,0 +1,38 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEAze9G/3GB2UDA9WFtJpZ3F6gtpfvrBFq1WJSFAszcTYUWIyOFJhFR
|
||||
Kt67tYeit2VQCYtQ3Gbn+Z3tWV7cCdVMNSQOMBnSsPvU8AG+Rrm5/lRKMILetpCwD3goYj
|
||||
7nE1w9BQw4SFDgb9yscrXaySGALc2U9u0k7AYgxdfuy3d8JP9Q4PTQGiOquND5ronExAAk
|
||||
ER5+bJyNbffi4GU3d/zzxOaYyTNKMPfq+ppVFDOaBwpObGfAwbkUdUWpuLMafyxUDPvX3j
|
||||
Jlt2TNguQDdCRuAOzV55cIkypjVaxiNIhbnAQSoY8TdanYARddf+NnAq3qwvVFtWrk04vZ
|
||||
qsBCKgRi99FTj8vnQj0EFYj/gtPQgYMq98KWXIjyj9Zr5nDpAuRQ8yoPXt79SQatH6mYML
|
||||
fjzxvHBp8UQhhEPmTCw7gIsZEFBMA1njLJBy5G41BIlWcnVYgj0sxXMxrSmrUIkFWQOWcd
|
||||
Bp9rFGkI8pIVs6ijS/KCG6JRHZB/bmzmVjYtG681AAAFiJrvSX6a70l+AAAAB3NzaC1yc2
|
||||
EAAAGBAM3vRv9xgdlAwPVhbSaWdxeoLaX76wRatViUhQLM3E2FFiMjhSYRUSreu7WHordl
|
||||
UAmLUNxm5/md7Vle3AnVTDUkDjAZ0rD71PABvka5uf5USjCC3raQsA94KGI+5xNcPQUMOE
|
||||
hQ4G/crHK12skhgC3NlPbtJOwGIMXX7st3fCT/UOD00BojqrjQ+a6JxMQAJBEefmycjW33
|
||||
4uBlN3f888TmmMkzSjD36vqaVRQzmgcKTmxnwMG5FHVFqbizGn8sVAz7194yZbdkzYLkA3
|
||||
QkbgDs1eeXCJMqY1WsYjSIW5wEEqGPE3Wp2AEXXX/jZwKt6sL1RbVq5NOL2arAQioEYvfR
|
||||
U4/L50I9BBWI/4LT0IGDKvfCllyI8o/Wa+Zw6QLkUPMqD17e/UkGrR+pmDC3488bxwafFE
|
||||
IYRD5kwsO4CLGRBQTANZ4yyQcuRuNQSJVnJ1WII9LMVzMa0pq1CJBVkDlnHQafaxRpCPKS
|
||||
FbOoo0vyghuiUR2Qf25s5lY2LRuvNQAAAAMBAAEAAAGABvaYR/rmkRoHbESnFC7yR/J/2K
|
||||
T0BWmryBr9hGK48EYXwYhp8CeVvwVZA4Jaliju0+PKECnKnj4g0GzMs+hqc0GM2UOGREW/
|
||||
pX3pmSqeh2MCPzGtpi6uRVeixe+qkJUF2y3WmVtiu2WSzy4m/7YKR4I0D0VlgjWS1h2/DV
|
||||
I0+GtJqNGeV8Ps+eLXDnfKF3aJwapuS+3fOmCvYzcI8R20gGvrrqH1WEKJx3+AcPZttt86
|
||||
V6AKfIJtlqmMW5pywuoUveYGDLCbg1oajqh7o06eTiFqZuCzbKjJUahzc1IvjsMRmP8rij
|
||||
WVAVZdUV5NiLYjmPczxS12zcUCmPJo5geDQLpCJdfgFYWCk9nr08MCLXmD973S4egrfw33
|
||||
+WMblW7R6vkHFUYK1Nfxe+Ume3mag+KbRJc0fYrO4Y+1BrhnsO5lqRHjkvl4jldYkAoqly
|
||||
jnbk9PwWn4+u/FZ5mUyP7RCEK4INvXah/dG44GwRfY/OyoeQMM4P0BDedp5pGJn73hAAAA
|
||||
wQDvs3FzKxF8uZPyDBZjEbn61m6oTVXE9PRl1kSzxD2wPqmZUPr1WtK/1ugWSMBoFTk72J
|
||||
z5wXfaFVifz7U5EzQ23yZkBN2aL6jzu7H5OcxgZZVS3sL2WYfZ/lRphX0kHYBcM7ZChIbV
|
||||
sDmheqE0wVTdTP809j1NX/sQOBShVg7vj20VTRYQs7SCBzsPEAmXE6a1haWBKfrZfhPN/3
|
||||
xZJ162n2FA21LQjDcfHLWeSzSHjzdOK/3YSr/8o7EGqK7iTbYAAADBAPodvvOQvHm0k9Ki
|
||||
7BzTQCCWCog0jR26rKeH5QlCi6fwmWBFR1vVjrqBRzhPUIH0sml6yOlYqpiKi0cNTZZ3dP
|
||||
QuUU2U63AnyQyuSTAnOWy9mh9aAguWK4IdtuToH+rJCi4lyy4khFaeyzbbb6iD4HDR/sYF
|
||||
AARMj/rAHypcnUSwkwSRiRoFy2w/h21roIocgBFfrVJUe1RDHTB9tiDFTqQ/WKWJFPfBSV
|
||||
I4bqpWlFKFAIkbIaCEe2DIKHMp6ywNJwAAAMEA0sd18i4dOzDt0Sx+aYpK5tcx7G1Oen67
|
||||
8WddT5bO63R4yQ4gCumiH2GQTaEnQIe9iTZ5hMQiwJJcfP9zI60g0RgMabicAX6TmW6ej8
|
||||
4ZVfZhkQoCU15Ih4uIuCreSbwo/Q1FT48GA6UScqrDuSzaEenDuWKAv0NWap9B0Rro9eCb
|
||||
ppaSE8QmSoojWAEAnOjaL/ig7j808xaDlNiMXKnmMdV4Lrj2OzyhqE5LpL7fShqhQ5CryY
|
||||
l4Kj1BWsuKzJJDAAAAEWxhZ3Vub3ZAdW5pdC0xMzgxAQ==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -1,7 +1,20 @@
|
||||
/*
|
||||
* 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.math.BigDecimal;
|
||||
|
||||
public class JavaVersion {
|
||||
public static boolean isJava7OrEarlier() {
|
||||
String property = System.getProperty("java.specification.version");
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class Jdk7HttpProxySocket extends Socket {
|
||||
|
||||
@@ -33,7 +49,7 @@ public class Jdk7HttpProxySocket extends Socket {
|
||||
}
|
||||
InetSocketAddress isa = (InetSocketAddress) endpoint;
|
||||
String httpConnect = "CONNECT " + isa.getHostName() + ":" + isa.getPort() + " HTTP/1.0\n\n";
|
||||
getOutputStream().write(httpConnect.getBytes(Charset.forName("UTF-8")));
|
||||
getOutputStream().write(httpConnect.getBytes(IOUtils.UTF8));
|
||||
checkAndFlushProxyResponse();
|
||||
}
|
||||
|
||||
@@ -46,7 +62,7 @@ public class Jdk7HttpProxySocket extends Socket {
|
||||
throw new SocketException("Empty response from proxy");
|
||||
}
|
||||
|
||||
String proxyResponse = new String(tmpBuffer, 0, len, "UTF-8");
|
||||
String proxyResponse = new String(tmpBuffer, 0, len, IOUtils.UTF8);
|
||||
|
||||
// Expecting HTTP/1.x 200 OK
|
||||
if (proxyResponse.contains("200")) {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
31
src/main/java/com/hierynomus/sshj/common/KeyAlgorithm.java
Normal file
31
src/main/java/com/hierynomus/sshj/common/KeyAlgorithm.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.common;
|
||||
|
||||
public class KeyAlgorithm {
|
||||
|
||||
public static final String RSA = "RSA";
|
||||
public static final String DSA = "DSA";
|
||||
|
||||
/** Elliptic curve signature key algorithm for use with BouncyCastle **/
|
||||
public static final String ECDSA = "ECDSA";
|
||||
|
||||
/** General elliptic curve algorithm identifier for use with BouncyCastle **/
|
||||
public static final String EC_BC = "EC";
|
||||
|
||||
/** General elliptic curve algorithm identifier for use with the Android Keystore **/
|
||||
public static final String EC_KEYSTORE = "EC";
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.common;
|
||||
|
||||
import org.bouncycastle.openssl.EncryptionException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Thrown when a key file could not be decrypted correctly, e.g. if its checkInts differed in the case of an OpenSSH
|
||||
* key file.
|
||||
*/
|
||||
public class KeyDecryptionFailedException extends IOException {
|
||||
|
||||
public static final String MESSAGE = "Decryption of the key failed. A supplied passphrase may be incorrect.";
|
||||
|
||||
public KeyDecryptionFailedException() {
|
||||
super(MESSAGE);
|
||||
}
|
||||
|
||||
public KeyDecryptionFailedException(EncryptionException cause) {
|
||||
super(MESSAGE, cause);
|
||||
}
|
||||
|
||||
}
|
||||
60
src/main/java/com/hierynomus/sshj/key/BaseKeyAlgorithm.java
Normal file
60
src/main/java/com/hierynomus/sshj/key/BaseKeyAlgorithm.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.key;
|
||||
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.KeyType;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class BaseKeyAlgorithm implements KeyAlgorithm {
|
||||
private final String keyAlgorithm;
|
||||
private final Factory.Named<Signature> signature;
|
||||
private final KeyType keyFormat;
|
||||
|
||||
public BaseKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
|
||||
this.keyAlgorithm = keyAlgorithm;
|
||||
this.signature = signature;
|
||||
this.keyFormat = keyFormat;
|
||||
}
|
||||
|
||||
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||
keyFormat.putPubKeyIntoBuffer(pk, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException {
|
||||
return keyFormat.readPubKeyFromBuffer(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyAlgorithm() {
|
||||
return keyAlgorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyType getKeyFormat() {
|
||||
return keyFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Signature newSignature() {
|
||||
return this.signature.create();
|
||||
}
|
||||
}
|
||||
45
src/main/java/com/hierynomus/sshj/key/KeyAlgorithm.java
Normal file
45
src/main/java/com/hierynomus/sshj/key/KeyAlgorithm.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.key;
|
||||
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.KeyType;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* In [RFC4252], the concept "public key algorithm" is used to establish
|
||||
* a relationship between one algorithm name, and:
|
||||
* <p>
|
||||
* A. procedures used to generate and validate a private/public
|
||||
* keypair;
|
||||
* B. a format used to encode a public key; and
|
||||
* C. procedures used to calculate, encode, and verify a signature.
|
||||
*/
|
||||
public interface KeyAlgorithm {
|
||||
|
||||
PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException;
|
||||
|
||||
void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf);
|
||||
|
||||
String getKeyAlgorithm();
|
||||
|
||||
KeyType getKeyFormat();
|
||||
|
||||
Signature newSignature();
|
||||
}
|
||||
65
src/main/java/com/hierynomus/sshj/key/KeyAlgorithms.java
Normal file
65
src/main/java/com/hierynomus/sshj/key/KeyAlgorithms.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.key;
|
||||
|
||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
||||
import net.schmizz.sshj.common.KeyType;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
import net.schmizz.sshj.signature.SignatureDSA;
|
||||
import net.schmizz.sshj.signature.SignatureECDSA;
|
||||
import net.schmizz.sshj.signature.SignatureRSA;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class KeyAlgorithms {
|
||||
|
||||
public static List<String> SSH_RSA_SHA2_ALGORITHMS = Arrays.asList("rsa-sha2-512", "rsa-sha2-256");
|
||||
|
||||
public static Factory SSHRSA() { return new Factory("ssh-rsa", new SignatureRSA.FactorySSHRSA(), KeyType.RSA); }
|
||||
public static Factory SSHRSACertV01() { return new Factory("ssh-rsa-cert-v01@openssh.com", new SignatureRSA.FactoryCERT(), KeyType.RSA_CERT); }
|
||||
public static Factory RSASHA256() { return new Factory("rsa-sha2-256", new SignatureRSA.FactoryRSASHA256(), KeyType.RSA); }
|
||||
public static Factory RSASHA512() { return new Factory("rsa-sha2-512", new SignatureRSA.FactoryRSASHA512(), KeyType.RSA); }
|
||||
public static Factory SSHDSA() { return new Factory(KeyType.DSA.toString(), new SignatureDSA.Factory(), KeyType.DSA); }
|
||||
public static Factory SSHDSSCertV01() { return new Factory(KeyType.DSA_CERT.toString(), new SignatureDSA.Factory(), KeyType.DSA_CERT); }
|
||||
public static Factory ECDSASHANistp256() { return new Factory(KeyType.ECDSA256.toString(), new SignatureECDSA.Factory256(), KeyType.ECDSA256); }
|
||||
public static Factory ECDSASHANistp384() { return new Factory(KeyType.ECDSA384.toString(), new SignatureECDSA.Factory384(), KeyType.ECDSA384); }
|
||||
public static Factory ECDSASHANistp521() { return new Factory(KeyType.ECDSA521.toString(), new SignatureECDSA.Factory521(), KeyType.ECDSA521); }
|
||||
public static Factory EdDSA25519() { return new Factory(KeyType.ED25519.toString(), new SignatureEdDSA.Factory(), KeyType.ED25519); }
|
||||
|
||||
public static class Factory implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||
|
||||
private final String algorithmName;
|
||||
private final Named<Signature> signatureFactory;
|
||||
private final KeyType keyType;
|
||||
|
||||
public Factory(String algorithmName, Named<Signature> signatureFactory, KeyType keyType) {
|
||||
this.algorithmName = algorithmName;
|
||||
this.signatureFactory = signatureFactory;
|
||||
this.keyType = keyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return algorithmName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyAlgorithm create() {
|
||||
return new BaseKeyAlgorithm(algorithmName, signatureFactory, keyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -17,7 +32,7 @@ public class Ed25519PublicKey extends EdDSAPublicKey {
|
||||
public Ed25519PublicKey(EdDSAPublicKeySpec spec) {
|
||||
super(spec);
|
||||
|
||||
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("ed25519-sha-512");
|
||||
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("Ed25519");
|
||||
if (!spec.getParams().getCurve().equals(ed25519.getCurve())) {
|
||||
throw new SSHRuntimeException("Cannot create Ed25519 Public Key from wrong spec");
|
||||
}
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
/*
|
||||
* 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.Buffer;
|
||||
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.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SignatureException;
|
||||
|
||||
public class SignatureEdDSA implements Signature {
|
||||
public class SignatureEdDSA extends AbstractSignature {
|
||||
public static class Factory implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||
|
||||
@Override
|
||||
@@ -22,54 +39,18 @@ public class SignatureEdDSA implements Signature {
|
||||
}
|
||||
}
|
||||
|
||||
final EdDSAEngine engine;
|
||||
SignatureEdDSA() {
|
||||
super(getEngine(), KeyType.ED25519.toString());
|
||||
}
|
||||
|
||||
protected SignatureEdDSA() {
|
||||
private static EdDSAEngine getEngine() {
|
||||
try {
|
||||
engine = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
|
||||
return new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PublicKey pubkey, PrivateKey prvkey) {
|
||||
try {
|
||||
if (pubkey != null) {
|
||||
engine.initVerify(pubkey);
|
||||
}
|
||||
|
||||
if (prvkey != null) {
|
||||
engine.initSign(prvkey);
|
||||
}
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] H) {
|
||||
update(H, 0, H.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] H, int off, int len) {
|
||||
try {
|
||||
engine.update(H, off, len);
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] sign() {
|
||||
try {
|
||||
return engine.sign();
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode(byte[] signature) {
|
||||
return signature;
|
||||
@@ -78,17 +59,9 @@ public class SignatureEdDSA implements Signature {
|
||||
@Override
|
||||
public boolean verify(byte[] sig) {
|
||||
try {
|
||||
Buffer.PlainBuffer plainBuffer = new Buffer.PlainBuffer(sig);
|
||||
String algo = plainBuffer.readString();
|
||||
if (!"ssh-ed25519".equals(algo)) {
|
||||
throw new SSHRuntimeException("Expected 'ssh-ed25519' key algorithm, but was: " + algo);
|
||||
}
|
||||
byte[] bytes = plainBuffer.readBytes();
|
||||
return engine.verify(bytes);
|
||||
return signature.verify(extractSig(sig, "ssh-ed25519"));
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
} catch (Buffer.BufferException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,64 @@
|
||||
/*
|
||||
* 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 net.schmizz.sshj.transport.cipher.BlockCipher;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
|
||||
/**
|
||||
* All BlockCiphers supported by SSH according to the following RFCs
|
||||
* All BlockCiphers supported by SSH according to the following RFCs:
|
||||
*
|
||||
* - https://tools.ietf.org/html/rfc4344#section-3.1
|
||||
* - https://tools.ietf.org/html/rfc4253#section-6.3
|
||||
* <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>
|
||||
*
|
||||
* TODO: https://tools.ietf.org/html/rfc5647
|
||||
*
|
||||
* Some of the Ciphers are still implemented in net.schmizz.sshj.transport.cipher.*. These are scheduled to be migrated to here.
|
||||
* 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);
|
||||
}
|
||||
@@ -76,6 +113,9 @@ public class BlockCiphers {
|
||||
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
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -10,6 +25,7 @@ import static com.hierynomus.sshj.transport.cipher.BlockCiphers.COUNTER_MODE;
|
||||
*
|
||||
* - 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);
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
/*
|
||||
* 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;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class StreamCipher extends BaseCipher {
|
||||
|
||||
@@ -14,6 +28,6 @@ public class StreamCipher extends BaseCipher {
|
||||
|
||||
@Override
|
||||
protected void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
cipher.init(getMode(mode), getKeySpec(key), new SecureRandom());
|
||||
cipher.init(getMode(mode), getKeySpec(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -8,6 +23,7 @@ import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
* - 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() {
|
||||
|
||||
44
src/main/java/com/hierynomus/sshj/transport/kex/DHG.java
Normal file
44
src/main/java/com/hierynomus/sshj/transport/kex/DHG.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.kex.KeyExchange;
|
||||
|
||||
/**
|
||||
* Stub kex algorithm factory that indicates support for SSH2_MSG_EXT_INFO.
|
||||
* Some servers will not send `rsa-sha2-*` signatures if the client doesn't indicate support.
|
||||
*
|
||||
* Note: Since the server sends `ext-info-s` to indicate support, this fake kex algorithm is never negotiated.
|
||||
*/
|
||||
public class ExtInfoClientFactory implements net.schmizz.sshj.common.Factory.Named<KeyExchange> {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "ext-info-c";
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyExchange create() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
98
src/main/java/com/hierynomus/sshj/transport/mac/Macs.java
Normal file
98
src/main/java/com/hierynomus/sshj/transport/mac/Macs.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 + ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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.common.KeyAlgorithm;
|
||||
import com.hierynomus.sshj.common.KeyDecryptionFailedException;
|
||||
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));
|
||||
while (true) {
|
||||
PlainBuffer decryptionBuffer = new PlainBuffer(privateKeyBuffer);
|
||||
PlainBuffer decrypted = decryptBuffer(decryptionBuffer, cipherName, kdfName, kdfOptions);
|
||||
try {
|
||||
return readUnencrypted(decrypted, publicKey);
|
||||
} catch (KeyDecryptionFailedException e) {
|
||||
if (pwdf == null || !pwdf.shouldRetry(resource))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
// 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());
|
||||
Arrays.fill(charBuffer.array(), '\u0000');
|
||||
Arrays.fill(byteBuffer.array(), (byte) 0);
|
||||
}
|
||||
byte[] keyiv = new byte[48];
|
||||
new BCrypt().pbkdf(passphrase, opts.readBytes(), opts.readUInt32AsInt(), keyiv);
|
||||
Arrays.fill(passphrase, (byte) 0);
|
||||
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 KeyDecryptionFailedException();
|
||||
}
|
||||
// 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(KeyAlgorithm.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(KeyAlgorithm.ECDSA).generatePrivate(pks);
|
||||
|
||||
}
|
||||
}
|
||||
918
src/main/java/djb/Curve25519.java
Normal file
918
src/main/java/djb/Curve25519.java
Normal file
@@ -0,0 +1,918 @@
|
||||
/* 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
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package net.schmizz.concurrent;
|
||||
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -42,8 +44,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) {
|
||||
promise = new Promise<Object, T>(name, chainer);
|
||||
public Event(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
|
||||
promise = new Promise<Object, T>(name, chainer, loggerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,8 +55,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) {
|
||||
promise = new Promise<Object, T>(name, chainer, lock);
|
||||
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
|
||||
promise = new Promise<Object, T>(name, chainer, lock, loggerFactory);
|
||||
}
|
||||
|
||||
/** Sets this event to be {@code true}. Short for {@code set(true)}. */
|
||||
@@ -143,4 +145,4 @@ public class Event<T extends Throwable> {
|
||||
return promise.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -26,7 +26,7 @@ package net.schmizz.concurrent;
|
||||
* if (t instanceof SomeException)
|
||||
* return (SomeException) t;
|
||||
* else
|
||||
* return new SomeExcepion(t);
|
||||
* return new SomeException(t);
|
||||
* }
|
||||
* };
|
||||
* </pre>
|
||||
@@ -37,4 +37,4 @@ public interface ExceptionChainer<Z extends Throwable> {
|
||||
|
||||
Z chain(Throwable t);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -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,8 +32,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public class Promise<V, T extends Throwable> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final Logger log;
|
||||
private final String name;
|
||||
private final ExceptionChainer<T> chainer;
|
||||
private final ReentrantLock lock;
|
||||
@@ -49,8 +48,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) {
|
||||
this(name, chainer, null);
|
||||
public Promise(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
|
||||
this(name, chainer, null, loggerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +59,11 @@ 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) {
|
||||
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
|
||||
this.name = name;
|
||||
this.chainer = chainer;
|
||||
this.lock = lock == null ? new ReentrantLock() : lock;
|
||||
this.log = loggerFactory.getLogger(getClass());
|
||||
this.cond = this.lock.newCondition();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -19,18 +19,18 @@ 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 = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final Logger log;
|
||||
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);
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
public synchronized int getKeepAliveInterval() {
|
||||
@@ -65,6 +65,8 @@ 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -22,14 +22,13 @@ 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 = LoggerFactory.getLogger(getClass());
|
||||
protected final Logger log;
|
||||
|
||||
/** Assigned name of this service */
|
||||
protected final String name;
|
||||
@@ -39,6 +38,7 @@ public abstract class AbstractService
|
||||
public AbstractService(String name, Transport trans) {
|
||||
this.name = name;
|
||||
this.trans = trans;
|
||||
log = trans.getConfig().getLoggerFactory().getLogger(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,12 +15,35 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||
import com.hierynomus.sshj.key.KeyAlgorithms;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
import net.schmizz.sshj.transport.random.JCERandom;
|
||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Registers SpongyCastle as JCE provider.
|
||||
*/
|
||||
public class AndroidConfig
|
||||
extends DefaultConfig {
|
||||
|
||||
static {
|
||||
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initKeyAlgorithms() {
|
||||
setKeyAlgorithms(Arrays.<Factory.Named<KeyAlgorithm>>asList(
|
||||
KeyAlgorithms.EdDSA25519(),
|
||||
KeyAlgorithms.SSHRSA(),
|
||||
KeyAlgorithms.SSHDSA()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initRandomFactory(boolean ignored) {
|
||||
setRandomFactory(new SingletonRandomFactory(new JCERandom.Factory()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||
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;
|
||||
@@ -76,11 +78,11 @@ public interface Config {
|
||||
Factory<Random> getRandomFactory();
|
||||
|
||||
/**
|
||||
* Retrieve the list of named factories for {@link Signature}
|
||||
* Retrieve the list of named factories for {@link com.hierynomus.sshj.key.KeyAlgorithm}
|
||||
*
|
||||
* @return a list of named {@link Signature} factories
|
||||
* @return a list of named {@link com.hierynomus.sshj.key.KeyAlgorithm} factories
|
||||
*/
|
||||
List<Factory.Named<Signature>> getSignatureFactories();
|
||||
List<Factory.Named<KeyAlgorithm>> getKeyAlgorithms();
|
||||
|
||||
/**
|
||||
* Returns the software version information for identification during SSH connection initialization. For example,
|
||||
@@ -131,11 +133,11 @@ public interface Config {
|
||||
void setRandomFactory(Factory<Random> randomFactory);
|
||||
|
||||
/**
|
||||
* Set the named factories for {@link Signature}.
|
||||
* Set the named factories for {@link KeyAlgorithm}.
|
||||
*
|
||||
* @param signatureFactories a list of named factories
|
||||
* @param keyAlgorithms a list of named factories
|
||||
*/
|
||||
void setSignatureFactories(List<Factory.Named<Signature>> signatureFactories);
|
||||
void setKeyAlgorithms(List<Factory.Named<KeyAlgorithm>> keyAlgorithms);
|
||||
|
||||
/**
|
||||
* Set the software version information for identification during SSH connection initialization. For example, {@code
|
||||
@@ -155,4 +157,34 @@ 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();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
import net.schmizz.sshj.transport.compression.Compression;
|
||||
import net.schmizz.sshj.transport.kex.KeyExchange;
|
||||
@@ -41,9 +42,12 @@ public class ConfigImpl
|
||||
private List<Factory.Named<Cipher>> cipherFactories;
|
||||
private List<Factory.Named<Compression>> compressionFactories;
|
||||
private List<Factory.Named<MAC>> macFactories;
|
||||
private List<Factory.Named<Signature>> signatureFactories;
|
||||
private List<Factory.Named<KeyAlgorithm>> keyAlgorithms;
|
||||
private List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories;
|
||||
|
||||
private boolean waitForServerIdentBeforeSendingClientIdent = false;
|
||||
private LoggerFactory loggerFactory;
|
||||
|
||||
@Override
|
||||
public List<Factory.Named<Cipher>> getCipherFactories() {
|
||||
return cipherFactories;
|
||||
@@ -74,11 +78,6 @@ public class ConfigImpl
|
||||
return randomFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Factory.Named<Signature>> getSignatureFactories() {
|
||||
return signatureFactories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
@@ -134,15 +133,6 @@ public class ConfigImpl
|
||||
this.randomFactory = randomFactory;
|
||||
}
|
||||
|
||||
public void setSignatureFactories(Factory.Named<Signature>... signatureFactories) {
|
||||
setSignatureFactories(Arrays.asList(signatureFactories));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSignatureFactories(List<Factory.Named<Signature>> signatureFactories) {
|
||||
this.signatureFactories = signatureFactories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
@@ -157,4 +147,34 @@ 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 List<Factory.Named<KeyAlgorithm>> getKeyAlgorithms() {
|
||||
return keyAlgorithms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyAlgorithms(List<Factory.Named<KeyAlgorithm>> keyAlgorithms) {
|
||||
this.keyAlgorithms = keyAlgorithms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggerFactory getLoggerFactory() {
|
||||
return loggerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggerFactory(LoggerFactory loggerFactory) {
|
||||
this.loggerFactory = loggerFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,47 +15,35 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
||||
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||
import com.hierynomus.sshj.key.KeyAlgorithms;
|
||||
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.ExtInfoClientFactory;
|
||||
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.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.*;
|
||||
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.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.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 org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.image.ByteLookupTable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A {@link net.schmizz.sshj.Config} that is initialized as follows. Items marked with an asterisk are added to the config only if
|
||||
@@ -63,13 +51,11 @@ import java.util.List;
|
||||
* <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} [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#setCipherFactories Ciphers}: {@link BlockCiphers}, {@link StreamCiphers} [1]</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>
|
||||
* <li>{@link net.schmizz.sshj.ConfigImpl#setSignatureFactories Signature}: {@link net.schmizz.sshj.signature.SignatureRSA}, {@link net.schmizz.sshj.signature.SignatureDSA}</li>
|
||||
* <li>{@link net.schmizz.sshj.ConfigImpl#setKeyAlgorithms KeyAlgorithm}: {@link net.schmizz.sshj.signature.SignatureRSA}, {@link net.schmizz.sshj.signature.SignatureDSA}</li>
|
||||
* <li>{@link net.schmizz.sshj.ConfigImpl#setRandomFactory PRNG}: {@link net.schmizz.sshj.transport.random.BouncyCastleRandom}* or {@link net.schmizz.sshj.transport.random.JCERandom}</li>
|
||||
* <li>{@link net.schmizz.sshj.ConfigImpl#setFileKeyProviderFactories Key file support}: {@link net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile}*, {@link
|
||||
* net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile}*</li>
|
||||
@@ -82,59 +68,110 @@ import java.util.List;
|
||||
public class DefaultConfig
|
||||
extends ConfigImpl {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private static final String VERSION = "SSHJ_0_14_0";
|
||||
private Logger log;
|
||||
|
||||
public DefaultConfig() {
|
||||
setVersion(VERSION);
|
||||
setLoggerFactory(LoggerFactory.DEFAULT);
|
||||
setVersion(readVersionFromProperties());
|
||||
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
|
||||
initKeyExchangeFactories(bouncyCastleRegistered);
|
||||
initKeyAlgorithms();
|
||||
initRandomFactory(bouncyCastleRegistered);
|
||||
initFileKeyProviderFactories(bouncyCastleRegistered);
|
||||
initCipherFactories();
|
||||
initCompressionFactories();
|
||||
initMACFactories();
|
||||
initSignatureFactories();
|
||||
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(),
|
||||
if (bouncyCastleRegistered) {
|
||||
setKeyExchangeFactories(
|
||||
new Curve25519SHA256.Factory(),
|
||||
new Curve25519SHA256.FactoryLibSsh(),
|
||||
new DHGexSHA256.Factory(),
|
||||
new ECDHNistP.Factory521(),
|
||||
new ECDHNistP.Factory384(),
|
||||
new ECDHNistP.Factory256(),
|
||||
new DHGexSHA1.Factory(),
|
||||
new DHG14.Factory(),
|
||||
new DHG1.Factory());
|
||||
else
|
||||
setKeyExchangeFactories(new DHG1.Factory(), 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(),
|
||||
new ExtInfoClientFactory());
|
||||
} else {
|
||||
setKeyExchangeFactories(DHGroups.Group1SHA1(), new DHGexSHA1.Factory());
|
||||
}
|
||||
}
|
||||
|
||||
protected void initKeyAlgorithms() {
|
||||
setKeyAlgorithms(Arrays.<Factory.Named<KeyAlgorithm>>asList(
|
||||
KeyAlgorithms.EdDSA25519(),
|
||||
KeyAlgorithms.ECDSASHANistp521(),
|
||||
KeyAlgorithms.ECDSASHANistp384(),
|
||||
KeyAlgorithms.ECDSASHANistp256(),
|
||||
KeyAlgorithms.RSASHA512(),
|
||||
KeyAlgorithms.RSASHA256(),
|
||||
KeyAlgorithms.SSHRSACertV01(),
|
||||
KeyAlgorithms.SSHDSSCertV01(),
|
||||
KeyAlgorithms.SSHRSA(),
|
||||
KeyAlgorithms.SSHDSA()));
|
||||
}
|
||||
|
||||
protected void initRandomFactory(boolean bouncyCastleRegistered) {
|
||||
setRandomFactory(new SingletonRandomFactory(bouncyCastleRegistered
|
||||
? new BouncyCastleRandom.Factory() : new JCERandom.Factory()));
|
||||
setRandomFactory(new SingletonRandomFactory(new JCERandom.Factory()));
|
||||
}
|
||||
|
||||
protected void initFileKeyProviderFactories(boolean bouncyCastleRegistered) {
|
||||
if (bouncyCastleRegistered) {
|
||||
setFileKeyProviderFactories(new PKCS8KeyFile.Factory(), new OpenSSHKeyFile.Factory(), new PuTTYKeyFile.Factory());
|
||||
setFileKeyProviderFactories(
|
||||
new OpenSSHKeyV1KeyFile.Factory(),
|
||||
new PKCS8KeyFile.Factory(),
|
||||
new PKCS5KeyFile.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(
|
||||
new AES128CTR.Factory(),
|
||||
new AES192CTR.Factory(),
|
||||
new AES256CTR.Factory(),
|
||||
new AES128CBC.Factory(),
|
||||
new AES192CBC.Factory(),
|
||||
new AES256CBC.Factory(),
|
||||
new TripleDESCBC.Factory(),
|
||||
new BlowfishCBC.Factory(),
|
||||
BlockCiphers.AES128CBC(),
|
||||
BlockCiphers.AES128CTR(),
|
||||
BlockCiphers.AES192CBC(),
|
||||
BlockCiphers.AES192CTR(),
|
||||
BlockCiphers.AES256CBC(),
|
||||
BlockCiphers.AES256CTR(),
|
||||
BlockCiphers.BlowfishCBC(),
|
||||
BlockCiphers.BlowfishCTR(),
|
||||
BlockCiphers.Cast128CBC(),
|
||||
BlockCiphers.Cast128CTR(),
|
||||
@@ -146,6 +183,7 @@ public class DefaultConfig
|
||||
BlockCiphers.Serpent192CTR(),
|
||||
BlockCiphers.Serpent256CBC(),
|
||||
BlockCiphers.Serpent256CTR(),
|
||||
BlockCiphers.TripleDESCBC(),
|
||||
BlockCiphers.TripleDESCTR(),
|
||||
BlockCiphers.Twofish128CBC(),
|
||||
BlockCiphers.Twofish128CTR(),
|
||||
@@ -156,7 +194,8 @@ public class DefaultConfig
|
||||
BlockCiphers.TwofishCBC(),
|
||||
StreamCiphers.Arcfour(),
|
||||
StreamCiphers.Arcfour128(),
|
||||
StreamCiphers.Arcfour256()));
|
||||
StreamCiphers.Arcfour256())
|
||||
);
|
||||
|
||||
boolean warn = false;
|
||||
// Ref. https://issues.apache.org/jira/browse/SSHD-24
|
||||
@@ -181,18 +220,28 @@ public class DefaultConfig
|
||||
log.debug("Available cipher factories: {}", avail);
|
||||
}
|
||||
|
||||
protected void initSignatureFactories() {
|
||||
setSignatureFactories(new SignatureECDSA.Factory(), new SignatureRSA.Factory(), new SignatureDSA.Factory(), new SignatureEdDSA.Factory());
|
||||
}
|
||||
|
||||
protected void initMACFactories() {
|
||||
setMACFactories(new HMACSHA1.Factory(), new HMACSHA196.Factory(), new HMACMD5.Factory(),
|
||||
new HMACMD596.Factory(), new HMACSHA2256.Factory(), new HMACSHA2512.Factory());
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
protected void initCompressionFactories() {
|
||||
setCompressionFactories(new NoneCompression.Factory());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -15,16 +15,11 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
import net.schmizz.sshj.common.*;
|
||||
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.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.direct.*;
|
||||
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;
|
||||
@@ -40,43 +35,30 @@ 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.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.AuthGssApiWithMic;
|
||||
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.keyprovider.*;
|
||||
import net.schmizz.sshj.userauth.method.*;
|
||||
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.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Secure SHell client API.
|
||||
@@ -127,7 +109,8 @@ public class SSHClient
|
||||
public static final int DEFAULT_PORT = 22;
|
||||
|
||||
/** Logger */
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
protected final LoggerFactory loggerFactory;
|
||||
protected final Logger log;
|
||||
|
||||
/** Transport layer */
|
||||
protected final Transport trans;
|
||||
@@ -138,6 +121,11 @@ 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());
|
||||
@@ -150,6 +138,8 @@ 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());
|
||||
@@ -176,19 +166,23 @@ public class SSHClient
|
||||
|
||||
/**
|
||||
* Add a {@link HostKeyVerifier} that will verify any host that's able to claim a host key with the given {@code
|
||||
* fingerprint}, e.g. {@code "4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"}
|
||||
* 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>
|
||||
*
|
||||
* @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(new HostKeyVerifier() {
|
||||
@Override
|
||||
public boolean verify(String h, int p, PublicKey k) {
|
||||
return SecurityUtils.getFingerprint(k).equals(fingerprint);
|
||||
}
|
||||
});
|
||||
addHostKeyVerifier(FingerprintVerifier.getInstance(fingerprint));
|
||||
}
|
||||
|
||||
// FIXME: there are way too many auth... overrides. Better API needed.
|
||||
@@ -222,6 +216,7 @@ 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;
|
||||
@@ -293,6 +288,22 @@ 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}.
|
||||
@@ -307,7 +318,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");
|
||||
authPublickey(username, base + "id_rsa", base + "id_dsa", base + "id_ed25519", base + "id_ecdsa");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,8 +356,7 @@ 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));
|
||||
}
|
||||
|
||||
@@ -414,6 +424,14 @@ 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();
|
||||
}
|
||||
@@ -423,6 +441,15 @@ 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) {
|
||||
@@ -488,7 +515,7 @@ public class SSHClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for createing a {@link KeyProvider} instance from given location on the file system. Creates a
|
||||
* Utility function for creating 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)}.
|
||||
*
|
||||
@@ -507,8 +534,13 @@ public class SSHClient
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
* 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>
|
||||
* <p/>
|
||||
*
|
||||
* @param location the location of the key file
|
||||
@@ -613,7 +645,7 @@ public class SSHClient
|
||||
*/
|
||||
public void loadKnownHosts(File location)
|
||||
throws IOException {
|
||||
addHostKeyVerifier(new OpenSSHKnownHosts(location));
|
||||
addHostKeyVerifier(new OpenSSHKnownHosts(location, loggerFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,9 +661,25 @@ public class SSHClient
|
||||
*
|
||||
* @return a {@link LocalPortForwarder}
|
||||
*/
|
||||
public LocalPortForwarder newLocalPortForwarder(LocalPortForwarder.Parameters parameters,
|
||||
public LocalPortForwarder newLocalPortForwarder(Parameters parameters,
|
||||
ServerSocket serverSocket) {
|
||||
return new LocalPortForwarder(conn, parameters, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -658,7 +706,7 @@ public class SSHClient
|
||||
public SCPFileTransfer newSCPFileTransfer() {
|
||||
checkConnected();
|
||||
checkAuthenticated();
|
||||
return new SCPFileTransfer(this);
|
||||
return new SCPFileTransfer(this, loggerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -674,6 +722,19 @@ public class SSHClient
|
||||
return new SFTPClient(new SFTPEngine(this).init());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stateful FTP client is required in order to connect to Serv-U FTP servers.
|
||||
* @return Instantiated {@link SFTPClient} implementation.
|
||||
*
|
||||
* @throws IOException if there is an error starting the {@code sftp} subsystem
|
||||
*/
|
||||
public SFTPClient newStatefulSFTPClient()
|
||||
throws IOException {
|
||||
checkConnected();
|
||||
checkAuthenticated();
|
||||
return new StatefulSFTPClient(new SFTPEngine(this).init());
|
||||
}
|
||||
|
||||
/**
|
||||
* Does key re-exchange.
|
||||
*
|
||||
@@ -684,19 +745,29 @@ 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);
|
||||
final SessionChannel sess = new SessionChannel(conn, remoteCharset);
|
||||
sess.open();
|
||||
return sess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code zlib} compression to preferred compression algorithms. There is no guarantee that it will be
|
||||
* successfully negotiatied.
|
||||
* successfully negotiated.
|
||||
* <p/>
|
||||
* If the client is already connected renegotiation is done; otherwise this method simply returns (and compression
|
||||
* will be negotiated during connection establishment).
|
||||
@@ -759,4 +830,4 @@ public class SSHClient
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
/*
|
||||
* 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.
|
||||
@@ -17,6 +17,8 @@ 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;
|
||||
@@ -43,41 +45,28 @@ public abstract class SocketClient {
|
||||
private int timeout = 0;
|
||||
|
||||
private String hostname;
|
||||
private int port;
|
||||
|
||||
private boolean tunneled = false;
|
||||
|
||||
SocketClient(int defaultPort) {
|
||||
this.defaultPort = defaultPort;
|
||||
}
|
||||
|
||||
public void connect(InetAddress host, int port) throws IOException {
|
||||
socket = socketFactory.createSocket();
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
onConnect();
|
||||
protected InetSocketAddress makeInetSocketAddress(String hostname, int port) {
|
||||
return new InetSocketAddress(hostname, port);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param host The host address to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @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(InetAddress host, int port, Proxy proxy) throws IOException {
|
||||
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, int port) throws IOException {
|
||||
this.hostname = hostname;
|
||||
connect(InetAddress.getByName(hostname), port);
|
||||
public void connect(String hostname, Proxy proxy) throws IOException {
|
||||
connect(hostname, defaultPort, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,30 +80,17 @@ public abstract class SocketClient {
|
||||
@Deprecated
|
||||
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 {
|
||||
socket = socketFactory.createSocket();
|
||||
socket.bind(new InetSocketAddress(localAddr, localPort));
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param host The host address to connect to.
|
||||
@@ -129,14 +105,86 @@ public abstract class SocketClient {
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param hostname The host name to connect to.
|
||||
* @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(String hostname, Proxy proxy) throws IOException {
|
||||
connect(hostname, defaultPort, proxy);
|
||||
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;
|
||||
socket = socketFactory.createSocket();
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -155,15 +203,15 @@ public abstract class SocketClient {
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return (socket != null) && socket.isConnected();
|
||||
return tunneled || ((socket != null) && socket.isConnected());
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
return socket.getLocalPort();
|
||||
return tunneled ? 65536 : socket.getLocalPort();
|
||||
}
|
||||
|
||||
public InetAddress getLocalAddress() {
|
||||
return socket.getLocalAddress();
|
||||
return socket == null ? null : socket.getLocalAddress();
|
||||
}
|
||||
|
||||
public String getRemoteHostname() {
|
||||
@@ -171,11 +219,11 @@ public abstract class SocketClient {
|
||||
}
|
||||
|
||||
public int getRemotePort() {
|
||||
return socket.getPort();
|
||||
return socket == null ? this.port : socket.getPort();
|
||||
}
|
||||
|
||||
public InetAddress getRemoteAddress() {
|
||||
return socket.getInetAddress();
|
||||
return socket == null ? null : socket.getInetAddress();
|
||||
}
|
||||
|
||||
public void setSocketFactory(SocketFactory factory) {
|
||||
@@ -219,9 +267,11 @@ public abstract class SocketClient {
|
||||
}
|
||||
|
||||
void onConnect() throws IOException {
|
||||
socket.setSoTimeout(timeout);
|
||||
input = socket.getInputStream();
|
||||
output = socket.getOutputStream();
|
||||
if (socket != null) {
|
||||
socket.setSoTimeout(timeout);
|
||||
input = socket.getInputStream();
|
||||
output = socket.getOutputStream();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user