mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-08 00:00:54 +03:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fedf8c410c | ||
|
|
8b0d1ca03c | ||
|
|
91105e6a07 | ||
|
|
4e802cec86 | ||
|
|
dfdc464e08 | ||
|
|
fa7c40cc66 | ||
|
|
b1be9258b4 | ||
|
|
11543b2c00 | ||
|
|
3526694558 | ||
|
|
d618156ede | ||
|
|
98063680bc | ||
|
|
17754a65fe | ||
|
|
2bb52fcf7d | ||
|
|
1a70023e2d | ||
|
|
5e25c017bf | ||
|
|
27a5039831 | ||
|
|
c2d25a9d62 | ||
|
|
2a22809de2 | ||
|
|
9d1f6d9d83 | ||
|
|
4542d94440 | ||
|
|
46a0cbac9e | ||
|
|
f470ddf219 | ||
|
|
d09276fe01 | ||
|
|
241c355e20 | ||
|
|
56ef6c1223 |
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
|
||||||
|
|
||||||
1
.java-version
Normal file
1
.java-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
30
.travis.yml
30
.travis.yml
@@ -1,30 +0,0 @@
|
|||||||
language: java
|
|
||||||
dist: trusty
|
|
||||||
sudo: required
|
|
||||||
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8
|
|
||||||
- openjdk8
|
|
||||||
- oraclejdk9
|
|
||||||
|
|
||||||
before_cache:
|
|
||||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.gradle/caches/
|
|
||||||
- $HOME/.gradle/wrapper/
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- pip install --user codecov
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./gradlew check
|
|
||||||
- ./gradlew integrationTest
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- codecov
|
|
||||||
2
NOTICE
2
NOTICE
@@ -15,7 +15,7 @@ The Apache Software Foundation (http://www.apache.org/):
|
|||||||
== in this case for the SSHD distribution. ==
|
== 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:
|
the following license:
|
||||||
|
|
||||||
Copyright (c) 2002,2003,2004,2005,2006,2007,2008 Atsuhiko Yamanaka, JCraft,Inc.
|
Copyright (c) 2002,2003,2004,2005,2006,2007,2008 Atsuhiko Yamanaka, JCraft,Inc.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
= sshj - SSHv2 library for Java
|
= sshj - SSHv2 library for Java
|
||||||
Jeroen van Erp
|
Jeroen van Erp
|
||||||
:sshj_groupid: com.hierynomus
|
:sshj_groupid: com.hierynomus
|
||||||
:sshj_version: 0.27.0
|
:sshj_version: 0.29.0
|
||||||
:source-highlighter: pygments
|
:source-highlighter: pygments
|
||||||
|
|
||||||
image:https://api.bintray.com/packages/hierynomus/maven/sshj/images/download.svg[link="https://bintray.com/hierynomus/maven/sshj/_latestVersion"]
|
image:https://api.bintray.com/packages/hierynomus/maven/sshj/images/download.svg[link="https://bintray.com/hierynomus/maven/sshj/_latestVersion"]
|
||||||
@@ -73,7 +73,7 @@ key exchange::
|
|||||||
`diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
|
`diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
|
||||||
`ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
|
`ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
|
||||||
|
|
||||||
SSHJ also supports the following extended (non official) key exchange algoriths:
|
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-group14-sha256@ssh.com`, `diffie-hellman-group15-sha256`, `diffie-hellman-group15-sha256@ssh.com`, `diffie-hellman-group15-sha384@ssh.com`,
|
||||||
`diffie-hellman-group16-sha256`, `diffie-hellman-group16-sha384@ssh.com`, `diffie-hellman-group16-sha512@ssh.com`, `diffie-hellman-group18-sha512@ssh.com`
|
`diffie-hellman-group16-sha256`, `diffie-hellman-group16-sha384@ssh.com`, `diffie-hellman-group16-sha512@ssh.com`, `diffie-hellman-group18-sha512@ssh.com`
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ SSHJ 0.19.1 (2016-12-30)::
|
|||||||
* Enabled PKCS5 Key files in DefaultConfig
|
* 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/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
|
* 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 Hellmann KEX
|
* 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
|
* 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()
|
* LocalPortForwarder now correctly interrupts its own thread on close()
|
||||||
SSHJ 0.19.0 (2016-11-25)::
|
SSHJ 0.19.0 (2016-11-25)::
|
||||||
|
|||||||
70
build.gradle
70
build.gradle
@@ -6,16 +6,15 @@ plugins {
|
|||||||
id "java"
|
id "java"
|
||||||
id "groovy"
|
id "groovy"
|
||||||
id "jacoco"
|
id "jacoco"
|
||||||
id "osgi"
|
id "com.github.blindpirate.osgi" version '0.0.3'
|
||||||
id "maven-publish"
|
id "maven-publish"
|
||||||
id 'pl.allegro.tech.build.axion-release' version '1.9.2'
|
id 'pl.allegro.tech.build.axion-release' version '1.11.0'
|
||||||
id "com.bmuschko.docker-remote-api" version "3.2.1"
|
id "com.bmuschko.docker-remote-api" version "6.4.0"
|
||||||
id "com.github.hierynomus.license" version "0.12.1"
|
id "com.github.hierynomus.license" version "0.12.1"
|
||||||
id "com.jfrog.bintray" version "1.7"
|
id "com.jfrog.bintray" version "1.8.5"
|
||||||
id 'ru.vyarus.java-lib' version '1.0.5'
|
id 'ru.vyarus.java-lib' version '1.0.5'
|
||||||
// id 'ru.vyarus.pom' version '1.0.3'
|
// id 'ru.vyarus.pom' version '1.0.3'
|
||||||
id 'ru.vyarus.github-info' version '1.1.0'
|
id 'ru.vyarus.github-info' version '1.1.0'
|
||||||
id 'ru.vyarus.animalsniffer' version '1.4.2'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.hierynomus"
|
group = "com.hierynomus"
|
||||||
@@ -39,33 +38,28 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = 1.6
|
|
||||||
targetCompatibility = 1.6
|
|
||||||
|
|
||||||
configurations.compile.transitive = false
|
configurations.compile.transitive = false
|
||||||
|
|
||||||
def bouncycastleVersion = "1.60"
|
def bouncycastleVersion = "1.65"
|
||||||
def sshdVersion = "2.1.0"
|
def sshdVersion = "2.1.0"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
implementation "org.slf4j:slf4j-api:1.7.7"
|
||||||
|
implementation "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
|
||||||
|
implementation "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
|
||||||
|
implementation "com.jcraft:jzlib:1.1.3"
|
||||||
|
|
||||||
compile "org.slf4j:slf4j-api:1.7.7"
|
implementation "net.i2p.crypto:eddsa:0.3.0"
|
||||||
compile "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
|
|
||||||
compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
|
|
||||||
compile "com.jcraft:jzlib:1.1.3"
|
|
||||||
|
|
||||||
compile "net.i2p.crypto:eddsa:0.3.0"
|
testImplementation "junit:junit:4.12"
|
||||||
|
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.4'
|
||||||
testCompile "junit:junit:4.12"
|
testImplementation "org.mockito:mockito-core:2.28.2"
|
||||||
testCompile 'org.spockframework:spock-core:1.3-groovy-2.4'
|
testImplementation "org.apache.sshd:sshd-core:$sshdVersion"
|
||||||
testCompile "org.mockito:mockito-core:2.28.2"
|
testImplementation "org.apache.sshd:sshd-sftp:$sshdVersion"
|
||||||
testCompile "org.apache.sshd:sshd-core:$sshdVersion"
|
testImplementation "org.apache.sshd:sshd-scp:$sshdVersion"
|
||||||
testCompile "org.apache.sshd:sshd-sftp:$sshdVersion"
|
testRuntimeOnly "ch.qos.logback:logback-classic:1.2.3"
|
||||||
testCompile "org.apache.sshd:sshd-scp:$sshdVersion"
|
testImplementation 'org.glassfish.grizzly:grizzly-http-server:2.4.4'
|
||||||
testRuntime "ch.qos.logback:logback-classic:1.2.3"
|
testImplementation 'org.apache.httpcomponents:httpclient:4.5.9'
|
||||||
testCompile 'org.glassfish.grizzly:grizzly-http-server:2.4.4'
|
|
||||||
testCompile 'org.apache.httpcomponents:httpclient:4.5.9'
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +72,10 @@ license {
|
|||||||
excludes(['**/djb/Curve25519.java', '**/sshj/common/Base64.java', '**/org/mindrot/jbcrypt/*.java'])
|
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
|
// This disables the pedantic doclint feature of JDK8
|
||||||
if (JavaVersion.current().isJava8Compatible()) {
|
if (JavaVersion.current().isJava8Compatible()) {
|
||||||
tasks.withType(Javadoc) {
|
tasks.withType(Javadoc) {
|
||||||
@@ -85,6 +83,11 @@ if (JavaVersion.current().isJava8Compatible()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs.addAll(['--release', '7'])
|
||||||
|
}
|
||||||
|
|
||||||
task writeSshjVersionProperties {
|
task writeSshjVersionProperties {
|
||||||
doLast {
|
doLast {
|
||||||
project.file("${project.buildDir}/resources/main").mkdirs()
|
project.file("${project.buildDir}/resources/main").mkdirs()
|
||||||
@@ -129,8 +132,8 @@ sourcesJar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
integrationTestCompile.extendsFrom testCompile
|
integrationTestImplementation.extendsFrom testImplementation
|
||||||
integrationTestRuntime.extendsFrom testRuntime
|
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@@ -223,7 +226,7 @@ if (project.hasProperty("bintrayUsername") && project.hasProperty("bintrayApiKey
|
|||||||
publications = ["maven"]
|
publications = ["maven"]
|
||||||
pkg {
|
pkg {
|
||||||
repo = "maven"
|
repo = "maven"
|
||||||
name = project.name
|
name = "${project.name}"
|
||||||
licenses = ["Apache-2.0"]
|
licenses = ["Apache-2.0"]
|
||||||
vcsUrl = "https://github.com/hierynomus/sshj.git"
|
vcsUrl = "https://github.com/hierynomus/sshj.git"
|
||||||
labels = ["ssh", "sftp", "secure-shell", "network", "file-transfer"]
|
labels = ["ssh", "sftp", "secure-shell", "network", "file-transfer"]
|
||||||
@@ -257,22 +260,23 @@ jacocoTestReport {
|
|||||||
|
|
||||||
task buildItestImage(type: DockerBuildImage) {
|
task buildItestImage(type: DockerBuildImage) {
|
||||||
inputDir = file('src/itest/docker-image')
|
inputDir = file('src/itest/docker-image')
|
||||||
tag = 'sshj/sshd-itest'
|
images.add('sshj/sshd-itest:latest')
|
||||||
}
|
}
|
||||||
|
|
||||||
task createItestContainer(type: DockerCreateContainer) {
|
task createItestContainer(type: DockerCreateContainer) {
|
||||||
dependsOn buildItestImage
|
dependsOn buildItestImage
|
||||||
targetImageId { buildItestImage.getImageId() }
|
targetImageId buildItestImage.getImageId()
|
||||||
portBindings = ['2222:22']
|
hostConfig.portBindings = ['2222:22']
|
||||||
|
hostConfig.autoRemove = true
|
||||||
}
|
}
|
||||||
|
|
||||||
task startItestContainer(type: DockerStartContainer) {
|
task startItestContainer(type: DockerStartContainer) {
|
||||||
dependsOn createItestContainer
|
dependsOn createItestContainer
|
||||||
targetContainerId { createItestContainer.getContainerId() }
|
targetContainerId createItestContainer.getContainerId()
|
||||||
}
|
}
|
||||||
|
|
||||||
task stopItestContainer(type: DockerStopContainer) {
|
task stopItestContainer(type: DockerStopContainer) {
|
||||||
targetContainerId { createItestContainer.getContainerId() }
|
targetContainerId createItestContainer.getContainerId()
|
||||||
}
|
}
|
||||||
|
|
||||||
task forkedUploadRelease(type: GradleBuild) {
|
task forkedUploadRelease(type: GradleBuild) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
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 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=8626cbf206b4e201ade7b87779090690447054bc93f052954c78480fa6ed186e
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
51
gradlew
vendored
51
gradlew
vendored
@@ -1,5 +1,21 @@
|
|||||||
#!/usr/bin/env sh
|
#!/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.
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
## Gradle start up script for UN*X
|
## Gradle start up script for UN*X
|
||||||
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
|||||||
APP_BASE_NAME=`basename "$0"`
|
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.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS=""
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
@@ -109,8 +125,8 @@ if $darwin; then
|
|||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if $cygwin ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
@@ -138,19 +154,19 @@ if $cygwin ; then
|
|||||||
else
|
else
|
||||||
eval `echo args$i`="\"$arg\""
|
eval `echo args$i`="\"$arg\""
|
||||||
fi
|
fi
|
||||||
i=$((i+1))
|
i=`expr $i + 1`
|
||||||
done
|
done
|
||||||
case $i in
|
case $i in
|
||||||
(0) set -- ;;
|
0) set -- ;;
|
||||||
(1) set -- "$args0" ;;
|
1) set -- "$args0" ;;
|
||||||
(2) set -- "$args0" "$args1" ;;
|
2) set -- "$args0" "$args1" ;;
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -159,14 +175,9 @@ save () {
|
|||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
APP_ARGS=$(save "$@")
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# 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"
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
21
gradlew.bat
vendored
21
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
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@@ -13,8 +29,11 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
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.
|
@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 DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.hierynomus.sshj
|
package com.hierynomus.sshj
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.ECDSAKeyAlgorithm
|
||||||
|
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm
|
||||||
import com.hierynomus.sshj.signature.SignatureEdDSA
|
import com.hierynomus.sshj.signature.SignatureEdDSA
|
||||||
import net.schmizz.sshj.DefaultConfig
|
import net.schmizz.sshj.DefaultConfig
|
||||||
import net.schmizz.sshj.SSHClient
|
import net.schmizz.sshj.SSHClient
|
||||||
@@ -29,7 +31,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
|
|||||||
def "should accept correct key for #signatureName"() {
|
def "should accept correct key for #signatureName"() {
|
||||||
given:
|
given:
|
||||||
def config = new DefaultConfig()
|
def config = new DefaultConfig()
|
||||||
config.setSignatureFactories(signatureFactory)
|
config.setKeyAlgorithms(Collections.singletonList(signatureFactory))
|
||||||
SSHClient sshClient = new SSHClient(config)
|
SSHClient sshClient = new SSHClient(config)
|
||||||
sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint
|
sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
|
|||||||
sshClient.isConnected()
|
sshClient.isConnected()
|
||||||
|
|
||||||
where:
|
where:
|
||||||
signatureFactory << [new SignatureECDSA.Factory256(), new SignatureEdDSA.Factory()]
|
signatureFactory << [new ECDSAKeyAlgorithm.Factory256(), new EdDSAKeyAlgorithm.Factory()]
|
||||||
fingerprint << ["d3:6a:a9:52:05:ab:b5:48:dd:73:60:18:0c:3a:f0:a3", "dc:68:38:ce:fc:6f:2c:d6:6d:6b:34:eb:5c:f0:41:6a"]
|
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()
|
signatureName = signatureFactory.getName()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.RSAKeyAlgorithm
|
||||||
|
import net.schmizz.sshj.DefaultConfig
|
||||||
|
import net.schmizz.sshj.signature.SignatureRSA
|
||||||
|
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 << [new RSAKeyAlgorithm.FactorySSHRSA(), new RSAKeyAlgorithm.FactoryRSASHA256(), new RSAKeyAlgorithm.FactoryRSASHA512()]
|
||||||
|
sig = sigFactory.name
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,9 +17,6 @@ package com.hierynomus.sshj.transport.mac
|
|||||||
|
|
||||||
import com.hierynomus.sshj.IntegrationBaseSpec
|
import com.hierynomus.sshj.IntegrationBaseSpec
|
||||||
import net.schmizz.sshj.DefaultConfig
|
import net.schmizz.sshj.DefaultConfig
|
||||||
import net.schmizz.sshj.transport.mac.HMACRIPEMD160
|
|
||||||
import net.schmizz.sshj.transport.mac.HMACSHA2256
|
|
||||||
import spock.lang.AutoCleanup
|
|
||||||
import spock.lang.Unroll
|
import spock.lang.Unroll
|
||||||
|
|
||||||
class MacSpec extends IntegrationBaseSpec {
|
class MacSpec extends IntegrationBaseSpec {
|
||||||
|
|||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 abstract class AbstractKeyAlgorithm implements KeyAlgorithm {
|
||||||
|
private final String keyAlgorithm;
|
||||||
|
private final Factory.Named<Signature> signature;
|
||||||
|
private final KeyType keyFormat;
|
||||||
|
|
||||||
|
public AbstractKeyAlgorithm(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/main/java/com/hierynomus/sshj/key/DSAKeyAlgorithm.java
Normal file
65
src/main/java/com/hierynomus/sshj/key/DSAKeyAlgorithm.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 net.schmizz.sshj.common.Factory;
|
||||||
|
import net.schmizz.sshj.common.KeyType;
|
||||||
|
import net.schmizz.sshj.signature.Signature;
|
||||||
|
import net.schmizz.sshj.signature.SignatureDSA;
|
||||||
|
|
||||||
|
public class DSAKeyAlgorithm extends AbstractKeyAlgorithm {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the SSH-DSA key algorithm.
|
||||||
|
*/
|
||||||
|
public static class FactorySSHDSA
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new DSAKeyAlgorithm(KeyType.DSA.toString(), new SignatureDSA.Factory(), KeyType.DSA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.DSA.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the SSH-DSS-CERT key algorithm
|
||||||
|
*/
|
||||||
|
public static class FactorySSHDSSCert
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new DSAKeyAlgorithm(KeyType.DSA_CERT.toString(), new SignatureDSA.Factory(), KeyType.DSA_CERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.DSA_CERT.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
|
||||||
|
super(keyAlgorithm, signature, KeyType.DSA);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/main/java/com/hierynomus/sshj/key/ECDSAKeyAlgorithm.java
Normal file
72
src/main/java/com/hierynomus/sshj/key/ECDSAKeyAlgorithm.java
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.Factory;
|
||||||
|
import net.schmizz.sshj.common.KeyType;
|
||||||
|
import net.schmizz.sshj.signature.Signature;
|
||||||
|
import net.schmizz.sshj.signature.SignatureECDSA;
|
||||||
|
|
||||||
|
public class ECDSAKeyAlgorithm extends AbstractKeyAlgorithm {
|
||||||
|
/** A named factory for ECDSA-256 signature */
|
||||||
|
public static class Factory256 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new ECDSAKeyAlgorithm(KeyType.ECDSA256.toString(), new SignatureECDSA.Factory256(), KeyType.ECDSA256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.ECDSA256.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A named factory for ECDSA-384 signature */
|
||||||
|
public static class Factory384 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new ECDSAKeyAlgorithm(KeyType.ECDSA384.toString(), new SignatureECDSA.Factory384(), KeyType.ECDSA384);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.ECDSA384.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A named factory for ECDSA-521 signature */
|
||||||
|
public static class Factory521 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new ECDSAKeyAlgorithm(KeyType.ECDSA521.toString(), new SignatureECDSA.Factory384(), KeyType.ECDSA521);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.ECDSA521.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ECDSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
|
||||||
|
super(keyAlgorithm, signature, keyFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main/java/com/hierynomus/sshj/key/EdDSAKeyAlgorithm.java
Normal file
39
src/main/java/com/hierynomus/sshj/key/EdDSAKeyAlgorithm.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public class EdDSAKeyAlgorithm extends AbstractKeyAlgorithm {
|
||||||
|
public static class Factory implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.ED25519.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new EdDSAKeyAlgorithm(KeyType.ED25519.toString(), new SignatureEdDSA.Factory(), KeyType.ED25519);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EdDSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
|
||||||
|
super(keyAlgorithm, signature, keyFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
}
|
||||||
96
src/main/java/com/hierynomus/sshj/key/RSAKeyAlgorithm.java
Normal file
96
src/main/java/com/hierynomus/sshj/key/RSAKeyAlgorithm.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.Factory;
|
||||||
|
import net.schmizz.sshj.common.KeyType;
|
||||||
|
import net.schmizz.sshj.signature.Signature;
|
||||||
|
import net.schmizz.sshj.signature.SignatureRSA;
|
||||||
|
|
||||||
|
public class RSAKeyAlgorithm extends AbstractKeyAlgorithm {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the SSH-RSA (SHA1) public key algorithm
|
||||||
|
*/
|
||||||
|
public static class FactorySSHRSA
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new RSAKeyAlgorithm("ssh-rsa", new SignatureRSA.FactorySSHRSA(), KeyType.RSA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "ssh-rsa";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the ssh-rsa-cert-v01@openssh.com (SHA1) public key algorithm
|
||||||
|
*/
|
||||||
|
public static class FactorySSHRSACert
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new RSAKeyAlgorithm("ssh-rsa-cert-v01@openssh.com", new SignatureRSA.FactoryCERT(), KeyType.RSA_CERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "ssh-rsa-cert-v01@openssh.com";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the RSA-SHA2-256 public key algorithm
|
||||||
|
*/
|
||||||
|
public static class FactoryRSASHA256
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new RSAKeyAlgorithm("rsa-sha2-256", new SignatureRSA.FactoryRSASHA256(), KeyType.RSA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "rsa-sha2-256";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named factory for the RSA-SHA2-512 public key algorithm
|
||||||
|
*/
|
||||||
|
public static class FactoryRSASHA512
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm create() {
|
||||||
|
return new RSAKeyAlgorithm("rsa-sha2-512", new SignatureRSA.FactoryRSASHA512(), KeyType.RSA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "rsa-sha2-512";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
|
||||||
|
super(keyAlgorithm, signature, keyFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ public class SignatureEdDSA extends AbstractSignature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SignatureEdDSA() {
|
SignatureEdDSA() {
|
||||||
super(getEngine());
|
super(getEngine(), KeyType.ED25519.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EdDSAEngine getEngine() {
|
private static EdDSAEngine getEngine() {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.math.BigInteger;
|
|||||||
import static net.schmizz.sshj.transport.kex.DHGroupData.*;
|
import static net.schmizz.sshj.transport.kex.DHGroupData.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory methods for Diffie Hellmann KEX algorithms based on MODP groups / Oakley Groups
|
* Factory methods for Diffie Hellman KEX algorithms based on MODP groups / Oakley Groups
|
||||||
*
|
*
|
||||||
* - https://tools.ietf.org/html/rfc4253
|
* - https://tools.ietf.org/html/rfc4253
|
||||||
* - https://tools.ietf.org/html/draft-ietf-curdle-ssh-modp-dh-sha2-01
|
* - https://tools.ietf.org/html/draft-ietf-curdle-ssh-modp-dh-sha2-01
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.hierynomus.sshj.userauth.keyprovider;
|
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 com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
||||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||||
@@ -111,8 +113,16 @@ public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
|
|||||||
return readUnencrypted(privateKeyBuffer, publicKey);
|
return readUnencrypted(privateKeyBuffer, publicKey);
|
||||||
} else {
|
} else {
|
||||||
logger.info("Keypair is encrypted with: " + cipherName + ", " + kdfName + ", " + Arrays.toString(kdfOptions));
|
logger.info("Keypair is encrypted with: " + cipherName + ", " + kdfName + ", " + Arrays.toString(kdfOptions));
|
||||||
PlainBuffer decrypted = decryptBuffer(privateKeyBuffer, cipherName, kdfName, kdfOptions);
|
while (true) {
|
||||||
return readUnencrypted(decrypted, publicKey);
|
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.");
|
// throw new IOException("Cannot read encrypted keypair with " + cipherName + " yet.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +194,7 @@ public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
|
|||||||
int checkInt1 = keyBuffer.readUInt32AsInt(); // uint32 checkint1
|
int checkInt1 = keyBuffer.readUInt32AsInt(); // uint32 checkint1
|
||||||
int checkInt2 = keyBuffer.readUInt32AsInt(); // uint32 checkint2
|
int checkInt2 = keyBuffer.readUInt32AsInt(); // uint32 checkint2
|
||||||
if (checkInt1 != checkInt2) {
|
if (checkInt1 != checkInt2) {
|
||||||
throw new IOException("The checkInts differed, the key was not correctly decoded.");
|
throw new KeyDecryptionFailedException();
|
||||||
}
|
}
|
||||||
// The private key section contains both the public key and the private key
|
// The private key section contains both the public key and the private key
|
||||||
String keyType = keyBuffer.readString(); // string keytype
|
String keyType = keyBuffer.readString(); // string keytype
|
||||||
@@ -207,7 +217,7 @@ public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
|
|||||||
keyBuffer.readMPInt(); // iqmp (q^-1 mod p)
|
keyBuffer.readMPInt(); // iqmp (q^-1 mod p)
|
||||||
keyBuffer.readMPInt(); // p (Prime 1)
|
keyBuffer.readMPInt(); // p (Prime 1)
|
||||||
keyBuffer.readMPInt(); // q (Prime 2)
|
keyBuffer.readMPInt(); // q (Prime 2)
|
||||||
kp = new KeyPair(publicKey, SecurityUtils.getKeyFactory("RSA").generatePrivate(new RSAPrivateKeySpec(n, d)));
|
kp = new KeyPair(publicKey, SecurityUtils.getKeyFactory(KeyAlgorithm.RSA).generatePrivate(new RSAPrivateKeySpec(n, d)));
|
||||||
break;
|
break;
|
||||||
case ECDSA256:
|
case ECDSA256:
|
||||||
kp = new KeyPair(publicKey, createECDSAPrivateKey(kt, keyBuffer, "P-256"));
|
kp = new KeyPair(publicKey, createECDSAPrivateKey(kt, keyBuffer, "P-256"));
|
||||||
@@ -239,7 +249,7 @@ public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
|
|||||||
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
|
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
|
||||||
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
|
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
|
||||||
ECPrivateKeySpec pks = new ECPrivateKeySpec(s, ecCurveSpec);
|
ECPrivateKeySpec pks = new ECPrivateKeySpec(s, ecCurveSpec);
|
||||||
return SecurityUtils.getKeyFactory("ECDSA").generatePrivate(pks);
|
return SecurityUtils.getKeyFactory(KeyAlgorithm.ECDSA).generatePrivate(pks);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ package net.schmizz.concurrent;
|
|||||||
* if (t instanceof SomeException)
|
* if (t instanceof SomeException)
|
||||||
* return (SomeException) t;
|
* return (SomeException) t;
|
||||||
* else
|
* else
|
||||||
* return new SomeExcepion(t);
|
* return new SomeException(t);
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj;
|
package net.schmizz.sshj;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.DSAKeyAlgorithm;
|
||||||
|
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm;
|
||||||
|
import com.hierynomus.sshj.key.RSAKeyAlgorithm;
|
||||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
||||||
|
|
||||||
import net.schmizz.sshj.common.SecurityUtils;
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
@@ -23,6 +26,8 @@ import net.schmizz.sshj.signature.SignatureRSA;
|
|||||||
import net.schmizz.sshj.transport.random.JCERandom;
|
import net.schmizz.sshj.transport.random.JCERandom;
|
||||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers SpongyCastle as JCE provider.
|
* Registers SpongyCastle as JCE provider.
|
||||||
*/
|
*/
|
||||||
@@ -33,11 +38,14 @@ public class AndroidConfig
|
|||||||
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't add ECDSA
|
|
||||||
protected void initSignatureFactories() {
|
@Override
|
||||||
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory(),
|
protected void initKeyAlgorithms() {
|
||||||
// but add EdDSA
|
setKeyAlgorithms(Arrays.asList(
|
||||||
new SignatureEdDSA.Factory());
|
new EdDSAKeyAlgorithm.Factory(),
|
||||||
|
new RSAKeyAlgorithm.FactorySSHRSA(),
|
||||||
|
new DSAKeyAlgorithm.FactorySSHDSA()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj;
|
package net.schmizz.sshj;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.keepalive.KeepAliveProvider;
|
import net.schmizz.keepalive.KeepAliveProvider;
|
||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.common.LoggerFactory;
|
import net.schmizz.sshj.common.LoggerFactory;
|
||||||
@@ -77,11 +78,11 @@ public interface Config {
|
|||||||
Factory<Random> getRandomFactory();
|
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,
|
* Returns the software version information for identification during SSH connection initialization. For example,
|
||||||
@@ -132,11 +133,11 @@ public interface Config {
|
|||||||
void setRandomFactory(Factory<Random> randomFactory);
|
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
|
* Set the software version information for identification during SSH connection initialization. For example, {@code
|
||||||
@@ -160,7 +161,7 @@ public interface Config {
|
|||||||
/**
|
/**
|
||||||
* Gets whether the client should first wait for a received server ident, before sending the client ident.
|
* Gets whether the client should first wait for a received server ident, before sending the client ident.
|
||||||
* <p/>
|
* <p/>
|
||||||
* <stong>NB:</stong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
|
* <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.
|
* The default value is set to false.
|
||||||
*
|
*
|
||||||
@@ -171,7 +172,7 @@ public interface Config {
|
|||||||
/**
|
/**
|
||||||
* Sets whether the SSH client should wait for a received server ident, before sending the client ident.
|
* Sets whether the SSH client should wait for a received server ident, before sending the client ident.
|
||||||
* <p/>
|
* <p/>
|
||||||
* <stong>NB:</stong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
|
* <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.
|
* @param waitForServerIdentBeforeSendingClientIdent Whether to wait for the server ident.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj;
|
package net.schmizz.sshj;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.keepalive.KeepAliveProvider;
|
import net.schmizz.keepalive.KeepAliveProvider;
|
||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.common.LoggerFactory;
|
import net.schmizz.sshj.common.LoggerFactory;
|
||||||
import net.schmizz.sshj.signature.Signature;
|
|
||||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||||
import net.schmizz.sshj.transport.compression.Compression;
|
import net.schmizz.sshj.transport.compression.Compression;
|
||||||
import net.schmizz.sshj.transport.kex.KeyExchange;
|
import net.schmizz.sshj.transport.kex.KeyExchange;
|
||||||
@@ -42,7 +42,7 @@ public class ConfigImpl
|
|||||||
private List<Factory.Named<Cipher>> cipherFactories;
|
private List<Factory.Named<Cipher>> cipherFactories;
|
||||||
private List<Factory.Named<Compression>> compressionFactories;
|
private List<Factory.Named<Compression>> compressionFactories;
|
||||||
private List<Factory.Named<MAC>> macFactories;
|
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 List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories;
|
||||||
|
|
||||||
private boolean waitForServerIdentBeforeSendingClientIdent = false;
|
private boolean waitForServerIdentBeforeSendingClientIdent = false;
|
||||||
@@ -78,11 +78,6 @@ public class ConfigImpl
|
|||||||
return randomFactory;
|
return randomFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Factory.Named<Signature>> getSignatureFactories() {
|
|
||||||
return signatureFactories;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return version;
|
return version;
|
||||||
@@ -138,15 +133,6 @@ public class ConfigImpl
|
|||||||
this.randomFactory = randomFactory;
|
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
|
@Override
|
||||||
public void setVersion(String version) {
|
public void setVersion(String version) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@@ -172,6 +158,16 @@ public class ConfigImpl
|
|||||||
this.waitForServerIdentBeforeSendingClientIdent = 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
|
@Override
|
||||||
public LoggerFactory getLoggerFactory() {
|
public LoggerFactory getLoggerFactory() {
|
||||||
return loggerFactory;
|
return loggerFactory;
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj;
|
package net.schmizz.sshj;
|
||||||
|
|
||||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
import com.hierynomus.sshj.key.DSAKeyAlgorithm;
|
||||||
|
import com.hierynomus.sshj.key.ECDSAKeyAlgorithm;
|
||||||
|
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm;
|
||||||
|
import com.hierynomus.sshj.key.RSAKeyAlgorithm;
|
||||||
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
||||||
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
|
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
|
||||||
import com.hierynomus.sshj.transport.kex.DHGroups;
|
import com.hierynomus.sshj.transport.kex.DHGroups;
|
||||||
@@ -26,10 +29,7 @@ import net.schmizz.keepalive.KeepAliveProvider;
|
|||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.common.LoggerFactory;
|
import net.schmizz.sshj.common.LoggerFactory;
|
||||||
import net.schmizz.sshj.common.SecurityUtils;
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
import net.schmizz.sshj.signature.SignatureDSA;
|
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||||
import net.schmizz.sshj.signature.SignatureECDSA;
|
|
||||||
import net.schmizz.sshj.signature.SignatureRSA;
|
|
||||||
import net.schmizz.sshj.transport.cipher.*;
|
|
||||||
import net.schmizz.sshj.transport.compression.NoneCompression;
|
import net.schmizz.sshj.transport.compression.NoneCompression;
|
||||||
import net.schmizz.sshj.transport.kex.Curve25519SHA256;
|
import net.schmizz.sshj.transport.kex.Curve25519SHA256;
|
||||||
import net.schmizz.sshj.transport.kex.DHGexSHA1;
|
import net.schmizz.sshj.transport.kex.DHGexSHA1;
|
||||||
@@ -56,7 +56,7 @@ import java.util.*;
|
|||||||
* <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
|
* <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>
|
* 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#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#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
|
* <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>
|
* net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile}*</li>
|
||||||
@@ -76,12 +76,12 @@ public class DefaultConfig
|
|||||||
setVersion(readVersionFromProperties());
|
setVersion(readVersionFromProperties());
|
||||||
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
|
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
|
||||||
initKeyExchangeFactories(bouncyCastleRegistered);
|
initKeyExchangeFactories(bouncyCastleRegistered);
|
||||||
|
initKeyAlgorithms();
|
||||||
initRandomFactory(bouncyCastleRegistered);
|
initRandomFactory(bouncyCastleRegistered);
|
||||||
initFileKeyProviderFactories(bouncyCastleRegistered);
|
initFileKeyProviderFactories(bouncyCastleRegistered);
|
||||||
initCipherFactories();
|
initCipherFactories();
|
||||||
initCompressionFactories();
|
initCompressionFactories();
|
||||||
initMACFactories();
|
initMACFactories();
|
||||||
initSignatureFactories();
|
|
||||||
setKeepAliveProvider(KeepAliveProvider.HEARTBEAT);
|
setKeepAliveProvider(KeepAliveProvider.HEARTBEAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ public class DefaultConfig
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoggerFactory(LoggerFactory loggerFactory) {
|
public void setLoggerFactory(LoggerFactory loggerFactory) {
|
||||||
super.setLoggerFactory(loggerFactory);
|
super.setLoggerFactory(loggerFactory);
|
||||||
log = loggerFactory.getLogger(getClass());
|
log = loggerFactory.getLogger(getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) {
|
protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) {
|
||||||
@@ -133,6 +133,20 @@ public class DefaultConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void initKeyAlgorithms() {
|
||||||
|
setKeyAlgorithms(Arrays.asList(
|
||||||
|
new EdDSAKeyAlgorithm.Factory(),
|
||||||
|
new ECDSAKeyAlgorithm.Factory521(),
|
||||||
|
new ECDSAKeyAlgorithm.Factory384(),
|
||||||
|
new ECDSAKeyAlgorithm.Factory256(),
|
||||||
|
new RSAKeyAlgorithm.FactoryRSASHA512(),
|
||||||
|
new RSAKeyAlgorithm.FactoryRSASHA256(),
|
||||||
|
new RSAKeyAlgorithm.FactorySSHRSACert(),
|
||||||
|
new DSAKeyAlgorithm.FactorySSHDSSCert(),
|
||||||
|
new RSAKeyAlgorithm.FactorySSHRSA(),
|
||||||
|
new DSAKeyAlgorithm.FactorySSHDSA()));
|
||||||
|
}
|
||||||
|
|
||||||
protected void initRandomFactory(boolean bouncyCastleRegistered) {
|
protected void initRandomFactory(boolean bouncyCastleRegistered) {
|
||||||
setRandomFactory(new SingletonRandomFactory(bouncyCastleRegistered
|
setRandomFactory(new SingletonRandomFactory(bouncyCastleRegistered
|
||||||
? new BouncyCastleRandom.Factory() : new JCERandom.Factory()));
|
? new BouncyCastleRandom.Factory() : new JCERandom.Factory()));
|
||||||
@@ -207,18 +221,6 @@ public class DefaultConfig
|
|||||||
log.debug("Available cipher factories: {}", avail);
|
log.debug("Available cipher factories: {}", avail);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initSignatureFactories() {
|
|
||||||
setSignatureFactories(
|
|
||||||
new SignatureEdDSA.Factory(),
|
|
||||||
new SignatureECDSA.Factory256(),
|
|
||||||
new SignatureECDSA.Factory384(),
|
|
||||||
new SignatureECDSA.Factory521(),
|
|
||||||
new SignatureRSA.Factory(),
|
|
||||||
new SignatureRSA.FactoryCERT(),
|
|
||||||
new SignatureDSA.Factory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initMACFactories() {
|
protected void initMACFactories() {
|
||||||
setMACFactories(
|
setMACFactories(
|
||||||
Macs.HMACSHA1(),
|
Macs.HMACSHA1(),
|
||||||
|
|||||||
@@ -515,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
|
* one-off {@link PasswordFinder} using {@link PasswordUtils#createOneOff(char[])}, and calls {@link
|
||||||
* #loadKeys(String, PasswordFinder)}.
|
* #loadKeys(String, PasswordFinder)}.
|
||||||
*
|
*
|
||||||
@@ -754,7 +754,7 @@ public class SSHClient
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds {@code zlib} compression to preferred compression algorithms. There is no guarantee that it will be
|
* Adds {@code zlib} compression to preferred compression algorithms. There is no guarantee that it will be
|
||||||
* successfully negotiatied.
|
* successfully negotiated.
|
||||||
* <p/>
|
* <p/>
|
||||||
* If the client is already connected renegotiation is done; otherwise this method simply returns (and compression
|
* If the client is already connected renegotiation is done; otherwise this method simply returns (and compression
|
||||||
* will be negotiated during connection establishment).
|
* will be negotiated during connection establishment).
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ public abstract class SocketClient {
|
|||||||
this.defaultPort = defaultPort;
|
this.defaultPort = defaultPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected InetSocketAddress makeInetSocketAddress(String hostname, int port) {
|
||||||
|
return new InetSocketAddress(hostname, port);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a host via a proxy.
|
* Connect to a host via a proxy.
|
||||||
* @param hostname The host name to connect to.
|
* @param hostname The host name to connect to.
|
||||||
@@ -83,7 +87,7 @@ public abstract class SocketClient {
|
|||||||
} else {
|
} else {
|
||||||
socket = new Socket(proxy);
|
socket = new Socket(proxy);
|
||||||
}
|
}
|
||||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
|
||||||
onConnect();
|
onConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +135,7 @@ public abstract class SocketClient {
|
|||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
socket = socketFactory.createSocket();
|
socket = socketFactory.createSocket();
|
||||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
|
||||||
onConnect();
|
onConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +148,7 @@ public abstract class SocketClient {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
socket = socketFactory.createSocket();
|
socket = socketFactory.createSocket();
|
||||||
socket.bind(new InetSocketAddress(localAddr, localPort));
|
socket.bind(new InetSocketAddress(localAddr, localPort));
|
||||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
socket.connect(makeInetSocketAddress(hostname, port), connectTimeout);
|
||||||
onConnect();
|
onConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ package net.schmizz.sshj.common;
|
|||||||
* <a href="http://www.faqs.org/rfcs/rfc3548.html">RFC3548</a>.</li>
|
* <a href="http://www.faqs.org/rfcs/rfc3548.html">RFC3548</a>.</li>
|
||||||
* <li><em>Throws exceptions instead of returning null values.</em> Because some operations
|
* <li><em>Throws exceptions instead of returning null values.</em> Because some operations
|
||||||
* (especially those that may permit the GZIP option) use IO streams, there
|
* (especially those that may permit the GZIP option) use IO streams, there
|
||||||
* is a possiblity of an java.io.IOException being thrown. After some discussion and
|
* is a possibility of an java.io.IOException being thrown. After some discussion and
|
||||||
* thought, I've changed the behavior of the methods to throw java.io.IOExceptions
|
* thought, I've changed the behavior of the methods to throw java.io.IOExceptions
|
||||||
* rather than return null if ever there's an error. I think this is more
|
* rather than return null if ever there's an error. I think this is more
|
||||||
* appropriate, though it will require some changes to your code. Sorry,
|
* appropriate, though it will require some changes to your code. Sorry,
|
||||||
@@ -476,7 +476,7 @@ public class Base64
|
|||||||
* anywhere along their length by specifying
|
* anywhere along their length by specifying
|
||||||
* <var>srcOffset</var> and <var>destOffset</var>.
|
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||||
* This method does not check to make sure your arrays
|
* This method does not check to make sure your arrays
|
||||||
* are large enough to accomodate <var>srcOffset</var> + 3 for
|
* are large enough to accommodate <var>srcOffset</var> + 3 for
|
||||||
* the <var>source</var> array or <var>destOffset</var> + 4 for
|
* the <var>source</var> array or <var>destOffset</var> + 4 for
|
||||||
* the <var>destination</var> array.
|
* the <var>destination</var> array.
|
||||||
* The actual number of significant bytes in your array is
|
* The actual number of significant bytes in your array is
|
||||||
@@ -1007,7 +1007,7 @@ public class Base64
|
|||||||
* anywhere along their length by specifying
|
* anywhere along their length by specifying
|
||||||
* <var>srcOffset</var> and <var>destOffset</var>.
|
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||||
* This method does not check to make sure your arrays
|
* This method does not check to make sure your arrays
|
||||||
* are large enough to accomodate <var>srcOffset</var> + 4 for
|
* are large enough to accommodate <var>srcOffset</var> + 4 for
|
||||||
* the <var>source</var> array or <var>destOffset</var> + 3 for
|
* the <var>source</var> array or <var>destOffset</var> + 3 for
|
||||||
* the <var>destination</var> array.
|
* the <var>destination</var> array.
|
||||||
* This method returns the actual number of bytes that
|
* This method returns the actual number of bytes that
|
||||||
@@ -1928,7 +1928,7 @@ public class Base64
|
|||||||
if( suspendEncoding ) {
|
if( suspendEncoding ) {
|
||||||
this.out.write( theByte );
|
this.out.write( theByte );
|
||||||
return;
|
return;
|
||||||
} // end if: supsended
|
} // end if: suspended
|
||||||
|
|
||||||
// Encode?
|
// Encode?
|
||||||
if( encode ) {
|
if( encode ) {
|
||||||
@@ -1983,7 +1983,7 @@ public class Base64
|
|||||||
if( suspendEncoding ) {
|
if( suspendEncoding ) {
|
||||||
this.out.write( theBytes, off, len );
|
this.out.write( theBytes, off, len );
|
||||||
return;
|
return;
|
||||||
} // end if: supsended
|
} // end if: suspended
|
||||||
|
|
||||||
for( int i = 0; i < len; i++ ) {
|
for( int i = 0; i < len; i++ ) {
|
||||||
write( theBytes[ off + i ] );
|
write( theBytes[ off + i ] );
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.common;
|
package net.schmizz.sshj.common;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import com.hierynomus.sshj.secg.SecgUtils;
|
import com.hierynomus.sshj.secg.SecgUtils;
|
||||||
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
||||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||||
@@ -87,7 +88,7 @@ class ECDSAVariationsAdapter {
|
|||||||
ECPoint p = new ECPoint(bigX, bigY);
|
ECPoint p = new ECPoint(bigX, bigY);
|
||||||
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(p, ecCurveSpec);
|
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(p, ecCurveSpec);
|
||||||
|
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
KeyFactory keyFactory = KeyFactory.getInstance(KeyAlgorithm.ECDSA);
|
||||||
return keyFactory.generatePublic(publicKeySpec);
|
return keyFactory.generatePublic(publicKeySpec);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new GeneralSecurityException(ex);
|
throw new GeneralSecurityException(ex);
|
||||||
@@ -103,7 +104,7 @@ class ECDSAVariationsAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean isECKeyWithFieldSize(Key key, int fieldSize) {
|
static boolean isECKeyWithFieldSize(Key key, int fieldSize) {
|
||||||
return "ECDSA".equals(key.getAlgorithm())
|
return (KeyAlgorithm.ECDSA.equals(key.getAlgorithm()) || KeyAlgorithm.EC_KEYSTORE.equals(key.getAlgorithm()))
|
||||||
&& fieldSizeFromKey((ECKey) key) == fieldSize;
|
&& fieldSizeFromKey((ECKey) key) == fieldSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.util.List;
|
|||||||
public interface Factory<T> {
|
public interface Factory<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inteface for a named factory. Named factories are simply factories that are identified by a name. Such names are
|
* Interface for a named factory. Named factories are simply factories that are identified by a name. Such names are
|
||||||
* used mainly in SSH algorithm negotiation.
|
* used mainly in SSH algorithm negotiation.
|
||||||
*
|
*
|
||||||
* @param <T> type of object created by this factory
|
* @param <T> type of object created by this factory
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.common;
|
package net.schmizz.sshj.common;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import com.hierynomus.sshj.signature.Ed25519PublicKey;
|
import com.hierynomus.sshj.signature.Ed25519PublicKey;
|
||||||
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
||||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||||
@@ -30,9 +31,7 @@ import java.security.GeneralSecurityException;
|
|||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.interfaces.DSAPrivateKey;
|
|
||||||
import java.security.interfaces.DSAPublicKey;
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.DSAPublicKeySpec;
|
import java.security.spec.DSAPublicKeySpec;
|
||||||
import java.security.spec.RSAPublicKeySpec;
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
@@ -53,7 +52,7 @@ public enum KeyType {
|
|||||||
} catch (Buffer.BufferException be) {
|
} catch (Buffer.BufferException be) {
|
||||||
throw new GeneralSecurityException(be);
|
throw new GeneralSecurityException(be);
|
||||||
}
|
}
|
||||||
final KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
|
final KeyFactory keyFactory = SecurityUtils.getKeyFactory(KeyAlgorithm.RSA);
|
||||||
return keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
|
return keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ public enum KeyType {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isMyType(Key key) {
|
protected boolean isMyType(Key key) {
|
||||||
return (key instanceof RSAPublicKey || key instanceof RSAPrivateKey);
|
return KeyAlgorithm.RSA.equals(key.getAlgorithm());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ public enum KeyType {
|
|||||||
} catch (Buffer.BufferException be) {
|
} catch (Buffer.BufferException be) {
|
||||||
throw new GeneralSecurityException(be);
|
throw new GeneralSecurityException(be);
|
||||||
}
|
}
|
||||||
final KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
|
final KeyFactory keyFactory = SecurityUtils.getKeyFactory(KeyAlgorithm.DSA);
|
||||||
return keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
|
return keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +98,7 @@ public enum KeyType {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isMyType(Key key) {
|
protected boolean isMyType(Key key) {
|
||||||
return (key instanceof DSAPublicKey || key instanceof DSAPrivateKey);
|
return KeyAlgorithm.DSA.equals(key.getAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkClose() throws SSHException {
|
private void checkClose() throws SSHException {
|
||||||
if (closed) {
|
// Check whether either the Stream is closed, or the underlying channel is closed
|
||||||
|
if (closed || !chan.isOpen()) {
|
||||||
if (error != null)
|
if (error != null)
|
||||||
throw error;
|
throw error;
|
||||||
else
|
else
|
||||||
@@ -160,7 +161,8 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void close() throws IOException {
|
public synchronized void close() throws IOException {
|
||||||
if (!closed) {
|
// Not closed yet, and underlying channel is open to flush the data to.
|
||||||
|
if (!closed && chan.isOpen()) {
|
||||||
try {
|
try {
|
||||||
buffer.flush(false);
|
buffer.flush(false);
|
||||||
// trans.write(new SSHPacket(Message.CHANNEL_EOF).putUInt32(chan.getRecipient()));
|
// trans.write(new SSHPacket(Message.CHANNEL_EOF).putUInt32(chan.getRecipient()));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import net.schmizz.sshj.transport.TransportException;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/** Base class for direct channels whose open is initated by the client. */
|
/** Base class for direct channels whose open is initiated by the client. */
|
||||||
public abstract class AbstractDirectChannel
|
public abstract class AbstractDirectChannel
|
||||||
extends AbstractChannel
|
extends AbstractChannel
|
||||||
implements Channel.Direct {
|
implements Channel.Direct {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public interface Session
|
|||||||
TransportException;
|
TransportException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an enviornment variable.
|
* Set an environment variable.
|
||||||
*
|
*
|
||||||
* @param name name of the variable
|
* @param name name of the variable
|
||||||
* @param value value to set
|
* @param value value to set
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public interface ForwardedChannelOpener {
|
|||||||
/**
|
/**
|
||||||
* Delegates a {@code SSH_MSG_CHANNEL_OPEN} request for the channel type claimed by this opener.
|
* Delegates a {@code SSH_MSG_CHANNEL_OPEN} request for the channel type claimed by this opener.
|
||||||
*
|
*
|
||||||
* @param buf {@link SSHPacket} containg the request except for the message identifier and channel type field
|
* @param buf {@link SSHPacket} containing the request except for the message identifier and channel type field
|
||||||
*/
|
*/
|
||||||
void handleOpen(SSHPacket buf)
|
void handleOpen(SSHPacket buf)
|
||||||
throws ConnectionException, TransportException;
|
throws ConnectionException, TransportException;
|
||||||
|
|||||||
@@ -29,18 +29,26 @@ public abstract class AbstractSignature
|
|||||||
|
|
||||||
@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
|
@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
|
||||||
protected final java.security.Signature signature;
|
protected final java.security.Signature signature;
|
||||||
|
private final String signatureName;
|
||||||
|
|
||||||
protected AbstractSignature(String algorithm) {
|
protected AbstractSignature(String algorithm, String signatureName) {
|
||||||
try {
|
try {
|
||||||
this.signature = SecurityUtils.getSignature(algorithm);
|
this.signature = SecurityUtils.getSignature(algorithm);
|
||||||
|
this.signatureName = signatureName;
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new SSHRuntimeException(e);
|
throw new SSHRuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractSignature(@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
|
protected AbstractSignature(@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
|
||||||
java.security.Signature signatureEngine) {
|
java.security.Signature signatureEngine, String signatureName) {
|
||||||
this.signature = signatureEngine;
|
this.signature = signatureEngine;
|
||||||
|
this.signatureName = signatureName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignatureName() {
|
||||||
|
return signatureName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import java.security.PublicKey;
|
|||||||
/** Signature interface for SSH used to sign or verify data. Usually wraps a {@code javax.crypto.Signature} object. */
|
/** Signature interface for SSH used to sign or verify data. Usually wraps a {@code javax.crypto.Signature} object. */
|
||||||
public interface Signature {
|
public interface Signature {
|
||||||
|
|
||||||
|
String getSignatureName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this signature with the given public key for signature verification.
|
* Initialize this signature with the given public key for signature verification.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class SignatureDSA
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SignatureDSA() {
|
public SignatureDSA() {
|
||||||
super("SHA1withDSA");
|
super("SHA1withDSA", KeyType.DSA.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,8 +72,8 @@ public class SignatureDSA
|
|||||||
|
|
||||||
// result must be 40 bytes, but length of r and s may not be 20 bytes
|
// result must be 40 bytes, but length of r and s may not be 20 bytes
|
||||||
|
|
||||||
int r_copylen = (r.length < 20) ? r.length : 20;
|
int r_copylen = Math.min(r.length, 20);
|
||||||
int s_copylen = (s.length < 20) ? s.length : 20;
|
int s_copylen = Math.min(s.length, 20);
|
||||||
|
|
||||||
System.arraycopy(r, r.length - r_copylen, result, 20 - r_copylen, r_copylen);
|
System.arraycopy(r, r.length - r_copylen, result, 20 - r_copylen, r_copylen);
|
||||||
System.arraycopy(s, s.length - s_copylen, result, 40 - s_copylen, s_copylen);
|
System.arraycopy(s, s.length - s_copylen, result, 40 - s_copylen, s_copylen);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class SignatureECDSA extends AbstractSignature {
|
|||||||
private String keyTypeName;
|
private String keyTypeName;
|
||||||
|
|
||||||
public SignatureECDSA(String algorithm, String keyTypeName) {
|
public SignatureECDSA(String algorithm, String keyTypeName) {
|
||||||
super(algorithm);
|
super(algorithm, keyTypeName);
|
||||||
this.keyTypeName = keyTypeName;
|
this.keyTypeName = keyTypeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,26 +22,53 @@ import net.schmizz.sshj.common.SSHRuntimeException;
|
|||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/** RSA {@link Signature} */
|
/** RSA {@link Signature} */
|
||||||
public class SignatureRSA
|
public class SignatureRSA
|
||||||
extends AbstractSignature {
|
extends AbstractSignature {
|
||||||
|
|
||||||
/** A named factory for RSA {@link Signature} */
|
/** A named factory for RSA {@link Signature} */
|
||||||
public static class Factory
|
public static class FactorySSHRSA
|
||||||
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Signature create() {
|
public Signature create() {
|
||||||
return new SignatureRSA(KeyType.RSA.toString());
|
return new SignatureRSA("SHA1withRSA", KeyType.RSA, KeyType.RSA.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return KeyType.RSA.toString();
|
return KeyType.RSA.toString();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A named factory for RSA {@link Signature} */
|
||||||
|
public static class FactoryRSASHA256
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Signature create() {
|
||||||
|
return new SignatureRSA("SHA256withRSA", KeyType.RSA, "rsa-sha2-256");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "rsa-sha2-256";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** A named factory for RSA {@link Signature} */
|
||||||
|
public static class FactoryRSASHA512
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Signature create() {
|
||||||
|
return new SignatureRSA("SHA512withRSA", KeyType.RSA, "rsa-sha2-512");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "rsa-sha2-512";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A named factory for RSA {@link Signature} */
|
/** A named factory for RSA {@link Signature} */
|
||||||
@@ -50,7 +77,7 @@ public class SignatureRSA
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Signature create() {
|
public Signature create() {
|
||||||
return new SignatureRSA(KeyType.RSA_CERT.toString());
|
return new SignatureRSA("SHA1withRSA", KeyType.RSA_CERT, KeyType.RSA.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -60,19 +87,19 @@ public class SignatureRSA
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String keyTypeName;
|
private KeyType keyType;
|
||||||
|
|
||||||
|
|
||||||
public SignatureRSA(String keyTypeName) {
|
public SignatureRSA(String algorithm, KeyType keyType, String name) {
|
||||||
super("SHA1withRSA");
|
super(algorithm, name);
|
||||||
this.keyTypeName = keyTypeName;
|
this.keyType = keyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void initVerify(PublicKey publicKey) {
|
public void initVerify(PublicKey publicKey) {
|
||||||
try {
|
try {
|
||||||
if (this.keyTypeName.equals(KeyType.RSA_CERT.toString()) && publicKey instanceof Certificate) {
|
if (this.keyType.equals(KeyType.RSA_CERT) && publicKey instanceof Certificate) {
|
||||||
signature.initVerify(((Certificate<PublicKey>) publicKey).getKey());
|
signature.initVerify(((Certificate<PublicKey>) publicKey).getKey());
|
||||||
} else {
|
} else {
|
||||||
signature.initVerify(publicKey);
|
signature.initVerify(publicKey);
|
||||||
@@ -89,7 +116,7 @@ public class SignatureRSA
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(byte[] sig) {
|
public boolean verify(byte[] sig) {
|
||||||
sig = extractSig(sig, KeyType.RSA.toString());
|
sig = extractSig(sig, getSignatureName());
|
||||||
try {
|
try {
|
||||||
return signature.verify(sig);
|
return signature.verify(sig);
|
||||||
} catch (SignatureException e) {
|
} catch (SignatureException e) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport;
|
package net.schmizz.sshj.transport;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.concurrent.ErrorDeliveryUtil;
|
import net.schmizz.concurrent.ErrorDeliveryUtil;
|
||||||
import net.schmizz.concurrent.Event;
|
import net.schmizz.concurrent.Event;
|
||||||
import net.schmizz.sshj.common.*;
|
import net.schmizz.sshj.common.*;
|
||||||
@@ -30,9 +31,7 @@ import org.slf4j.Logger;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@@ -94,7 +93,7 @@ final class KeyExchanger
|
|||||||
* Add a callback for host key verification.
|
* Add a callback for host key verification.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Any of the {@link HostKeyVerifier} implementations added this way can deem a host key to be acceptable, allowing
|
* Any of the {@link HostKeyVerifier} implementations added this way can deem a host key to be acceptable, allowing
|
||||||
* key exchange to successfuly complete. Otherwise, a {@link TransportException} will result during key exchange.
|
* key exchange to successfully complete. Otherwise, a {@link TransportException} will result during key exchange.
|
||||||
*
|
*
|
||||||
* @param hkv object whose {@link HostKeyVerifier#verify} method will be invoked
|
* @param hkv object whose {@link HostKeyVerifier#verify} method will be invoked
|
||||||
*/
|
*/
|
||||||
@@ -232,6 +231,13 @@ final class KeyExchanger
|
|||||||
}
|
}
|
||||||
kex = Factory.Named.Util.create(transport.getConfig().getKeyExchangeFactories(),
|
kex = Factory.Named.Util.create(transport.getConfig().getKeyExchangeFactories(),
|
||||||
negotiatedAlgs.getKeyExchangeAlgorithm());
|
negotiatedAlgs.getKeyExchangeAlgorithm());
|
||||||
|
|
||||||
|
List<KeyAlgorithm> keyAlgorithms = new ArrayList<KeyAlgorithm>();
|
||||||
|
for (String signatureAlgorithm : negotiatedAlgs.getSignatureAlgorithms()) {
|
||||||
|
keyAlgorithms.add(Factory.Named.Util.create(transport.getConfig().getKeyAlgorithms(), signatureAlgorithm));
|
||||||
|
}
|
||||||
|
transport.setKeyAlgorithms(keyAlgorithms);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
kex.init(transport,
|
kex.init(transport,
|
||||||
transport.getServerID(), transport.getClientID(),
|
transport.getServerID(), transport.getClientID(),
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport;
|
package net.schmizz.sshj.transport;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public final class NegotiatedAlgorithms {
|
public final class NegotiatedAlgorithms {
|
||||||
|
|
||||||
private final String kex;
|
private final String kex;
|
||||||
private final String sig;
|
private final List<String> availableSigs;
|
||||||
private final String c2sCipher;
|
private final String c2sCipher;
|
||||||
private final String s2cCipher;
|
private final String s2cCipher;
|
||||||
private final String c2sMAC;
|
private final String c2sMAC;
|
||||||
@@ -26,10 +28,10 @@ public final class NegotiatedAlgorithms {
|
|||||||
private final String c2sComp;
|
private final String c2sComp;
|
||||||
private final String s2cComp;
|
private final String s2cComp;
|
||||||
|
|
||||||
NegotiatedAlgorithms(String kex, String sig, String c2sCipher, String s2cCipher, String c2sMAC, String s2cMAC,
|
NegotiatedAlgorithms(String kex, List<String> availableSigs, String c2sCipher, String s2cCipher, String c2sMAC, String s2cMAC,
|
||||||
String c2sComp, String s2cComp) {
|
String c2sComp, String s2cComp) {
|
||||||
this.kex = kex;
|
this.kex = kex;
|
||||||
this.sig = sig;
|
this.availableSigs = availableSigs;
|
||||||
this.c2sCipher = c2sCipher;
|
this.c2sCipher = c2sCipher;
|
||||||
this.s2cCipher = s2cCipher;
|
this.s2cCipher = s2cCipher;
|
||||||
this.c2sMAC = c2sMAC;
|
this.c2sMAC = c2sMAC;
|
||||||
@@ -42,8 +44,8 @@ public final class NegotiatedAlgorithms {
|
|||||||
return kex;
|
return kex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignatureAlgorithm() {
|
public List<String> getSignatureAlgorithms() {
|
||||||
return sig;
|
return availableSigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClient2ServerCipherAlgorithm() {
|
public String getClient2ServerCipherAlgorithm() {
|
||||||
@@ -74,7 +76,7 @@ public final class NegotiatedAlgorithms {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return ("[ " +
|
return ("[ " +
|
||||||
"kex=" + kex + "; " +
|
"kex=" + kex + "; " +
|
||||||
"sig=" + sig + "; " +
|
"availableSigs=" + availableSigs + "; " +
|
||||||
"c2sCipher=" + c2sCipher + "; " +
|
"c2sCipher=" + c2sCipher + "; " +
|
||||||
"s2cCipher=" + s2cCipher + "; " +
|
"s2cCipher=" + s2cCipher + "; " +
|
||||||
"c2sMAC=" + c2sMAC + "; " +
|
"c2sMAC=" + c2sMAC + "; " +
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import net.schmizz.sshj.common.Factory;
|
|||||||
import net.schmizz.sshj.common.Message;
|
import net.schmizz.sshj.common.Message;
|
||||||
import net.schmizz.sshj.common.SSHPacket;
|
import net.schmizz.sshj.common.SSHPacket;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ class Proposal {
|
|||||||
|
|
||||||
public Proposal(Config config) {
|
public Proposal(Config config) {
|
||||||
kex = Factory.Named.Util.getNames(config.getKeyExchangeFactories());
|
kex = Factory.Named.Util.getNames(config.getKeyExchangeFactories());
|
||||||
sig = Factory.Named.Util.getNames(config.getSignatureFactories());
|
sig = Factory.Named.Util.getNames(config.getKeyAlgorithms());
|
||||||
c2sCipher = s2cCipher = Factory.Named.Util.getNames(config.getCipherFactories());
|
c2sCipher = s2cCipher = Factory.Named.Util.getNames(config.getCipherFactories());
|
||||||
c2sMAC = s2cMAC = Factory.Named.Util.getNames(config.getMACFactories());
|
c2sMAC = s2cMAC = Factory.Named.Util.getNames(config.getMACFactories());
|
||||||
c2sComp = s2cComp = Factory.Named.Util.getNames(config.getCompressionFactories());
|
c2sComp = s2cComp = Factory.Named.Util.getNames(config.getCompressionFactories());
|
||||||
@@ -126,7 +127,7 @@ class Proposal {
|
|||||||
throws TransportException {
|
throws TransportException {
|
||||||
return new NegotiatedAlgorithms(
|
return new NegotiatedAlgorithms(
|
||||||
firstMatch(this.getKeyExchangeAlgorithms(), other.getKeyExchangeAlgorithms()),
|
firstMatch(this.getKeyExchangeAlgorithms(), other.getKeyExchangeAlgorithms()),
|
||||||
firstMatch(this.getSignatureAlgorithms(), other.getSignatureAlgorithms()),
|
allMatch(this.getSignatureAlgorithms(), other.getSignatureAlgorithms()),
|
||||||
firstMatch(this.getClient2ServerCipherAlgorithms(), other.getClient2ServerCipherAlgorithms()),
|
firstMatch(this.getClient2ServerCipherAlgorithms(), other.getClient2ServerCipherAlgorithms()),
|
||||||
firstMatch(this.getServer2ClientCipherAlgorithms(), other.getServer2ClientCipherAlgorithms()),
|
firstMatch(this.getServer2ClientCipherAlgorithms(), other.getServer2ClientCipherAlgorithms()),
|
||||||
firstMatch(this.getClient2ServerMACAlgorithms(), other.getClient2ServerMACAlgorithms()),
|
firstMatch(this.getClient2ServerMACAlgorithms(), other.getClient2ServerMACAlgorithms()),
|
||||||
@@ -138,19 +139,36 @@ class Proposal {
|
|||||||
|
|
||||||
private static String firstMatch(List<String> a, List<String> b)
|
private static String firstMatch(List<String> a, List<String> b)
|
||||||
throws TransportException {
|
throws TransportException {
|
||||||
for (String aa : a)
|
for (String aa : a) {
|
||||||
for (String bb : b)
|
if (b.contains(aa)) {
|
||||||
if (aa.equals(bb))
|
return aa;
|
||||||
return aa;
|
}
|
||||||
|
}
|
||||||
throw new TransportException("Unable to reach a settlement: " + a + " and " + b);
|
throw new TransportException("Unable to reach a settlement: " + a + " and " + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<String> allMatch(List<String> a, List<String> b) throws TransportException {
|
||||||
|
List<String> res = new ArrayList<String>();
|
||||||
|
for (String aa : a) {
|
||||||
|
if (b.contains(aa)) {
|
||||||
|
res.add(aa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.isEmpty()) {
|
||||||
|
throw new TransportException("Unable to reach a settlement: " + a + " and " + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private static String toCommaString(List<String> sl) {
|
private static String toCommaString(List<String> sl) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (String s : sl) {
|
for (String s : sl) {
|
||||||
if (i++ != 0)
|
if (i++ != 0) {
|
||||||
sb.append(",");
|
sb.append(",");
|
||||||
|
}
|
||||||
sb.append(s);
|
sb.append(s);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|||||||
@@ -15,9 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport;
|
package net.schmizz.sshj.transport;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.Config;
|
import net.schmizz.sshj.Config;
|
||||||
import net.schmizz.sshj.Service;
|
import net.schmizz.sshj.Service;
|
||||||
import net.schmizz.sshj.common.DisconnectReason;
|
import net.schmizz.sshj.common.DisconnectReason;
|
||||||
|
import net.schmizz.sshj.common.KeyType;
|
||||||
import net.schmizz.sshj.common.SSHPacket;
|
import net.schmizz.sshj.common.SSHPacket;
|
||||||
import net.schmizz.sshj.common.SSHPacketHandler;
|
import net.schmizz.sshj.common.SSHPacketHandler;
|
||||||
import net.schmizz.sshj.transport.verification.AlgorithmsVerifier;
|
import net.schmizz.sshj.transport.verification.AlgorithmsVerifier;
|
||||||
@@ -92,7 +94,7 @@ public interface Transport
|
|||||||
int getHeartbeatInterval();
|
int getHeartbeatInterval();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param interval the interval in seconds, {@code 0} means no hearbeat
|
* @param interval the interval in seconds, {@code 0} means no heartbeat
|
||||||
* @deprecated Moved to {@link net.schmizz.keepalive.KeepAlive#getKeepAliveInterval()}. This is accessible through the {@link net.schmizz.sshj.connection.Connection}.
|
* @deprecated Moved to {@link net.schmizz.keepalive.KeepAlive#getKeepAliveInterval()}. This is accessible through the {@link net.schmizz.sshj.connection.Connection}.
|
||||||
* Scheduled to be removed in 0.12.0
|
* Scheduled to be removed in 0.12.0
|
||||||
*/
|
*/
|
||||||
@@ -156,7 +158,7 @@ public interface Transport
|
|||||||
*
|
*
|
||||||
* @return the sequence number of the packet sent
|
* @return the sequence number of the packet sent
|
||||||
*
|
*
|
||||||
* @throws TransportException if an error occured sending the packet
|
* @throws TransportException if an error occurred sending the packet
|
||||||
*/
|
*/
|
||||||
long sendUnimplemented()
|
long sendUnimplemented()
|
||||||
throws TransportException;
|
throws TransportException;
|
||||||
@@ -235,4 +237,6 @@ public interface Transport
|
|||||||
* @param e The exception that occurred.
|
* @param e The exception that occurred.
|
||||||
*/
|
*/
|
||||||
void die(Exception e);
|
void die(Exception e);
|
||||||
|
|
||||||
|
KeyAlgorithm getKeyAlgorithm(KeyType keyType) throws TransportException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport;
|
package net.schmizz.sshj.transport;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import com.hierynomus.sshj.transport.IdentificationStringParser;
|
import com.hierynomus.sshj.transport.IdentificationStringParser;
|
||||||
import net.schmizz.concurrent.ErrorDeliveryUtil;
|
import net.schmizz.concurrent.ErrorDeliveryUtil;
|
||||||
import net.schmizz.concurrent.Event;
|
import net.schmizz.concurrent.Event;
|
||||||
@@ -30,6 +31,7 @@ import org.slf4j.Logger;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
public final class TransportImpl
|
public final class TransportImpl
|
||||||
implements Transport, DisconnectListener {
|
implements Transport, DisconnectListener {
|
||||||
|
|
||||||
|
|
||||||
private static final class NullService
|
private static final class NullService
|
||||||
extends AbstractService {
|
extends AbstractService {
|
||||||
|
|
||||||
@@ -86,6 +89,8 @@ public final class TransportImpl
|
|||||||
|
|
||||||
private final Decoder decoder;
|
private final Decoder decoder;
|
||||||
|
|
||||||
|
private List<KeyAlgorithm> keyAlgorithms;
|
||||||
|
|
||||||
private final Event<TransportException> serviceAccept;
|
private final Event<TransportException> serviceAccept;
|
||||||
|
|
||||||
private final Event<TransportException> close;
|
private final Event<TransportException> close;
|
||||||
@@ -104,6 +109,11 @@ public final class TransportImpl
|
|||||||
*/
|
*/
|
||||||
private volatile Service service;
|
private volatile Service service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The next service that will be activated, only set when sending an SSH_MSG_SERVICE_REQUEST
|
||||||
|
*/
|
||||||
|
private volatile Service nextService;
|
||||||
|
|
||||||
private DisconnectListener disconnectListener;
|
private DisconnectListener disconnectListener;
|
||||||
|
|
||||||
private ConnInfo connInfo;
|
private ConnInfo connInfo;
|
||||||
@@ -324,8 +334,9 @@ public final class TransportImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setService(Service service) {
|
public synchronized void setService(Service service) {
|
||||||
if (service == null)
|
if (service == null) {
|
||||||
service = nullService;
|
service = nullService;
|
||||||
|
}
|
||||||
|
|
||||||
log.debug("Setting active service to {}", service.getName());
|
log.debug("Setting active service to {}", service.getName());
|
||||||
this.service = service;
|
this.service = service;
|
||||||
@@ -337,11 +348,12 @@ public final class TransportImpl
|
|||||||
serviceAccept.lock();
|
serviceAccept.lock();
|
||||||
try {
|
try {
|
||||||
serviceAccept.clear();
|
serviceAccept.clear();
|
||||||
|
this.nextService = service;
|
||||||
sendServiceRequest(service.getName());
|
sendServiceRequest(service.getName());
|
||||||
serviceAccept.await(timeoutMs, TimeUnit.MILLISECONDS);
|
serviceAccept.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||||
setService(service);
|
|
||||||
} finally {
|
} finally {
|
||||||
serviceAccept.unlock();
|
serviceAccept.unlock();
|
||||||
|
this.nextService = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,8 +497,8 @@ public final class TransportImpl
|
|||||||
* This method is called in the context of the {@link #reader} thread via {@link Decoder#received} when a full
|
* This method is called in the context of the {@link #reader} thread via {@link Decoder#received} when a full
|
||||||
* packet has been decoded.
|
* packet has been decoded.
|
||||||
*
|
*
|
||||||
* @param msg the message identifer
|
* @param msg the message identifier
|
||||||
* @param buf buffer containg rest of the packet
|
* @param buf buffer containing rest of the packet
|
||||||
* @throws SSHException if an error occurs during handling (unrecoverable)
|
* @throws SSHException if an error occurs during handling (unrecoverable)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -496,13 +508,11 @@ public final class TransportImpl
|
|||||||
|
|
||||||
log.trace("Received packet {}", msg);
|
log.trace("Received packet {}", msg);
|
||||||
|
|
||||||
if (msg.geq(50)) // not a transport layer packet
|
if (msg.geq(50)) { // not a transport layer packet
|
||||||
service.handle(msg, buf);
|
service.handle(msg, buf);
|
||||||
|
} else if (msg.in(20, 21) || msg.in(30, 49)) { // kex packet
|
||||||
else if (msg.in(20, 21) || msg.in(30, 49)) // kex packet
|
|
||||||
kexer.handle(msg, buf);
|
kexer.handle(msg, buf);
|
||||||
|
} else {
|
||||||
else
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case DISCONNECT:
|
case DISCONNECT:
|
||||||
gotDisconnect(buf);
|
gotDisconnect(buf);
|
||||||
@@ -526,6 +536,7 @@ public final class TransportImpl
|
|||||||
sendUnimplemented();
|
sendUnimplemented();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gotDebug(SSHPacket buf)
|
private void gotDebug(SSHPacket buf)
|
||||||
@@ -558,6 +569,8 @@ public final class TransportImpl
|
|||||||
if (!serviceAccept.hasWaiters())
|
if (!serviceAccept.hasWaiters())
|
||||||
throw new TransportException(DisconnectReason.PROTOCOL_ERROR,
|
throw new TransportException(DisconnectReason.PROTOCOL_ERROR,
|
||||||
"Got a service accept notification when none was awaited");
|
"Got a service accept notification when none was awaited");
|
||||||
|
// Immediately switch to next service to prevent race condition mentioned in #559
|
||||||
|
setService(nextService);
|
||||||
serviceAccept.set();
|
serviceAccept.set();
|
||||||
} finally {
|
} finally {
|
||||||
serviceAccept.unlock();
|
serviceAccept.unlock();
|
||||||
@@ -641,4 +654,18 @@ public final class TransportImpl
|
|||||||
return connInfo;
|
return connInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyAlgorithm getKeyAlgorithm(KeyType keyType) throws TransportException {
|
||||||
|
for (KeyAlgorithm ka : keyAlgorithms) {
|
||||||
|
if (ka.getKeyFormat().equals(keyType)) {
|
||||||
|
return ka;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TransportException("Cannot find an available KeyAlgorithm for type " + keyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyAlgorithms(List<KeyAlgorithm> keyAlgorithms) {
|
||||||
|
this.keyAlgorithms = keyAlgorithms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ public abstract class AbstractDHG extends AbstractDH
|
|||||||
digest.update(buf.array(), buf.rpos(), buf.available());
|
digest.update(buf.array(), buf.rpos(), buf.available());
|
||||||
H = digest.digest();
|
H = digest.digest();
|
||||||
|
|
||||||
Signature signature = Factory.Named.Util.create(trans.getConfig().getSignatureFactories(),
|
|
||||||
KeyType.fromKey(hostKey).toString());
|
Signature signature = trans.getKeyAlgorithm(KeyType.fromKey(hostKey)).newSignature();
|
||||||
signature.initVerify(hostKey);
|
signature.initVerify(hostKey);
|
||||||
signature.update(H, 0, H.length);
|
signature.update(H, 0, H.length);
|
||||||
if (!signature.verify(sig))
|
if (!signature.verify(sig))
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport.kex;
|
package net.schmizz.sshj.transport.kex;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.*;
|
import net.schmizz.sshj.common.*;
|
||||||
import net.schmizz.sshj.signature.Signature;
|
import net.schmizz.sshj.signature.Signature;
|
||||||
import net.schmizz.sshj.transport.Transport;
|
import net.schmizz.sshj.transport.Transport;
|
||||||
@@ -30,9 +31,9 @@ import java.security.GeneralSecurityException;
|
|||||||
public abstract class AbstractDHGex extends AbstractDH {
|
public abstract class AbstractDHGex extends AbstractDH {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private int minBits = 1024;
|
private final int minBits = 1024;
|
||||||
private int maxBits = 8192;
|
private final int maxBits = 8192;
|
||||||
private int preferredBits = 2048;
|
private final int preferredBits = 2048;
|
||||||
|
|
||||||
public AbstractDHGex(Digest digest) {
|
public AbstractDHGex(Digest digest) {
|
||||||
super(new DH(), digest);
|
super(new DH(), digest);
|
||||||
@@ -84,8 +85,8 @@ public abstract class AbstractDHGex extends AbstractDH {
|
|||||||
.putMPInt(k);
|
.putMPInt(k);
|
||||||
digest.update(buf.array(), buf.rpos(), buf.available());
|
digest.update(buf.array(), buf.rpos(), buf.available());
|
||||||
H = digest.digest();
|
H = digest.digest();
|
||||||
Signature signature = Factory.Named.Util.create(trans.getConfig().getSignatureFactories(),
|
KeyAlgorithm keyAlgorithm = trans.getKeyAlgorithm(KeyType.fromKey(hostKey));
|
||||||
KeyType.fromKey(hostKey).toString());
|
Signature signature = keyAlgorithm.newSignature();
|
||||||
signature.initVerify(hostKey);
|
signature.initVerify(hostKey);
|
||||||
signature.update(H, 0, H.length);
|
signature.update(H, 0, H.length);
|
||||||
if (!signature.verify(sig))
|
if (!signature.verify(sig))
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport.kex;
|
package net.schmizz.sshj.transport.kex;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.transport.random.Random;
|
import net.schmizz.sshj.transport.random.Random;
|
||||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||||
@@ -31,7 +32,7 @@ public class Curve25519DH extends DHBase {
|
|||||||
private byte[] secretKey;
|
private byte[] secretKey;
|
||||||
|
|
||||||
public Curve25519DH() {
|
public Curve25519DH() {
|
||||||
super("ECDSA", "ECDH");
|
super(KeyAlgorithm.ECDSA, "ECDH");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport.kex;
|
package net.schmizz.sshj.transport.kex;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.common.SecurityUtils;
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
import net.schmizz.sshj.transport.random.Random;
|
import net.schmizz.sshj.transport.random.Random;
|
||||||
@@ -54,7 +55,7 @@ public class ECDH extends DHBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeK(byte[] f) throws GeneralSecurityException {
|
public void computeK(byte[] f) throws GeneralSecurityException {
|
||||||
KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
|
KeyFactory keyFactory = SecurityUtils.getKeyFactory(KeyAlgorithm.EC_BC);
|
||||||
ECPublicKeySpec keySpec = new ECPublicKeySpec(getDecoded(f, ecParameterSpec.getCurve()), ecParameterSpec);
|
ECPublicKeySpec keySpec = new ECPublicKeySpec(getDecoded(f, ecParameterSpec.getCurve()), ecParameterSpec);
|
||||||
PublicKey yourPubKey = keyFactory.generatePublic(keySpec);
|
PublicKey yourPubKey = keyFactory.generatePublic(keySpec);
|
||||||
agreement.doPhase(yourPubKey, true);
|
agreement.doPhase(yourPubKey, true);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.transport.verification;
|
package net.schmizz.sshj.transport.verification;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import com.hierynomus.sshj.transport.verification.KnownHostMatchers;
|
import com.hierynomus.sshj.transport.verification.KnownHostMatchers;
|
||||||
import net.schmizz.sshj.common.*;
|
import net.schmizz.sshj.common.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -190,7 +191,7 @@ public class OpenSSHKnownHosts
|
|||||||
* Lines starting with `#' and empty lines are ignored as comments.
|
* Lines starting with `#' and empty lines are ignored as comments.
|
||||||
*/
|
*/
|
||||||
public class EntryFactory {
|
public class EntryFactory {
|
||||||
EntryFactory() {
|
public EntryFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public KnownHostEntry parseEntry(String line)
|
public KnownHostEntry parseEntry(String line)
|
||||||
@@ -239,7 +240,7 @@ public class OpenSSHKnownHosts
|
|||||||
final BigInteger e = new BigInteger(split[i++]);
|
final BigInteger e = new BigInteger(split[i++]);
|
||||||
final BigInteger n = new BigInteger(split[i++]);
|
final BigInteger n = new BigInteger(split[i++]);
|
||||||
try {
|
try {
|
||||||
final KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
|
final KeyFactory keyFactory = SecurityUtils.getKeyFactory(KeyAlgorithm.RSA);
|
||||||
key = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
|
key = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error("Error reading entry `{}`, could not create key", line, ex);
|
log.error("Error reading entry `{}`, could not create key", line, ex);
|
||||||
@@ -387,7 +388,7 @@ public class OpenSSHKnownHosts
|
|||||||
line.append(" ").append(type.toString());
|
line.append(" ").append(type.toString());
|
||||||
line.append(" ").append(getKeyString(key));
|
line.append(" ").append(getKeyString(key));
|
||||||
|
|
||||||
if (!comment.isEmpty()) line.append(" ").append(comment);
|
if (comment != null && !comment.isEmpty()) line.append(" ").append(comment);
|
||||||
|
|
||||||
return line.toString();
|
return line.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.userauth.keyprovider;
|
package net.schmizz.sshj.userauth.keyprovider;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
||||||
import net.schmizz.sshj.common.Base64;
|
import net.schmizz.sshj.common.Base64;
|
||||||
import net.schmizz.sshj.common.ByteArrayUtils;
|
import net.schmizz.sshj.common.ByteArrayUtils;
|
||||||
@@ -140,7 +141,7 @@ public class PKCS5KeyFile extends BaseFileKeyProvider {
|
|||||||
ASN1Data asn = new ASN1Data(data = decrypt(Base64.decode(sb.toString()), cipher, iv));
|
ASN1Data asn = new ASN1Data(data = decrypt(Base64.decode(sb.toString()), cipher, iv));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RSA: {
|
case RSA: {
|
||||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
KeyFactory factory = KeyFactory.getInstance(KeyAlgorithm.RSA);
|
||||||
asn.readNext();
|
asn.readNext();
|
||||||
BigInteger modulus = asn.readNext();
|
BigInteger modulus = asn.readNext();
|
||||||
BigInteger pubExp = asn.readNext();
|
BigInteger pubExp = asn.readNext();
|
||||||
@@ -150,7 +151,7 @@ public class PKCS5KeyFile extends BaseFileKeyProvider {
|
|||||||
return new KeyPair(pubKey, prvKey);
|
return new KeyPair(pubKey, prvKey);
|
||||||
}
|
}
|
||||||
case DSA: {
|
case DSA: {
|
||||||
KeyFactory factory = KeyFactory.getInstance("DSA");
|
KeyFactory factory = KeyFactory.getInstance(KeyAlgorithm.DSA);
|
||||||
asn.readNext();
|
asn.readNext();
|
||||||
BigInteger p = asn.readNext();
|
BigInteger p = asn.readNext();
|
||||||
BigInteger q = asn.readNext();
|
BigInteger q = asn.readNext();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.userauth.keyprovider;
|
package net.schmizz.sshj.userauth.keyprovider;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyDecryptionFailedException;
|
||||||
import net.schmizz.sshj.common.IOUtils;
|
import net.schmizz.sshj.common.IOUtils;
|
||||||
import net.schmizz.sshj.common.SecurityUtils;
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
||||||
@@ -85,7 +86,7 @@ public class PKCS8KeyFile extends BaseFileKeyProvider {
|
|||||||
if (pwdf != null && pwdf.shouldRetry(resource))
|
if (pwdf != null && pwdf.shouldRetry(resource))
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
throw e;
|
throw new KeyDecryptionFailedException(e);
|
||||||
} finally {
|
} finally {
|
||||||
IOUtils.closeQuietly(r);
|
IOUtils.closeQuietly(r);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.userauth.keyprovider;
|
package net.schmizz.sshj.userauth.keyprovider;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.Base64;
|
import net.schmizz.sshj.common.Base64;
|
||||||
import net.schmizz.sshj.common.KeyType;
|
import net.schmizz.sshj.common.KeyType;
|
||||||
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
||||||
@@ -114,7 +115,7 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
|
|||||||
|
|
||||||
final KeyFactory factory;
|
final KeyFactory factory;
|
||||||
try {
|
try {
|
||||||
factory = KeyFactory.getInstance("RSA");
|
factory = KeyFactory.getInstance(KeyAlgorithm.RSA);
|
||||||
} catch (NoSuchAlgorithmException s) {
|
} catch (NoSuchAlgorithmException s) {
|
||||||
throw new IOException(s.getMessage(), s);
|
throw new IOException(s.getMessage(), s);
|
||||||
}
|
}
|
||||||
@@ -141,7 +142,7 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
|
|||||||
|
|
||||||
final KeyFactory factory;
|
final KeyFactory factory;
|
||||||
try {
|
try {
|
||||||
factory = KeyFactory.getInstance("DSA");
|
factory = KeyFactory.getInstance(KeyAlgorithm.DSA);
|
||||||
} catch (NoSuchAlgorithmException s) {
|
} catch (NoSuchAlgorithmException s) {
|
||||||
throw new IOException(s.getMessage(), s);
|
throw new IOException(s.getMessage(), s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
|
|||||||
/**
|
/**
|
||||||
* Implements the {@code "publickey"} SSH authentication method.
|
* Implements the {@code "publickey"} SSH authentication method.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Requesteing authentication with this method first sends a "feeler" request with just the public key, and if the
|
* Requesting authentication with this method first sends a "feeler" request with just the public key, and if the
|
||||||
* server responds with {@code SSH_MSG_USERAUTH_PK_OK} indicating that the key is acceptable, it proceeds to send a
|
* server responds with {@code SSH_MSG_USERAUTH_PK_OK} indicating that the key is acceptable, it proceeds to send a
|
||||||
* request signed with the private key. Therefore, private keys are not requested from the associated {@link
|
* request signed with the private key. Therefore, private keys are not requested from the associated {@link
|
||||||
* KeyProvider} unless needed.
|
* KeyProvider} unless needed.
|
||||||
|
|||||||
@@ -15,11 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.userauth.method;
|
package net.schmizz.sshj.userauth.method;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.key.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.Buffer;
|
import net.schmizz.sshj.common.Buffer;
|
||||||
import net.schmizz.sshj.common.Factory;
|
|
||||||
import net.schmizz.sshj.common.KeyType;
|
import net.schmizz.sshj.common.KeyType;
|
||||||
import net.schmizz.sshj.common.SSHPacket;
|
import net.schmizz.sshj.common.SSHPacket;
|
||||||
import net.schmizz.sshj.signature.Signature;
|
import net.schmizz.sshj.signature.Signature;
|
||||||
|
import net.schmizz.sshj.transport.TransportException;
|
||||||
import net.schmizz.sshj.userauth.UserAuthException;
|
import net.schmizz.sshj.userauth.UserAuthException;
|
||||||
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
|
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
|
||||||
|
|
||||||
@@ -47,9 +48,15 @@ public abstract class KeyedAuthMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
// public key as 2 strings: [ key type | key blob ]
|
// public key as 2 strings: [ key type | key blob ]
|
||||||
reqBuf.putString(KeyType.fromKey(key).toString())
|
KeyType keyType = KeyType.fromKey(key);
|
||||||
.putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
|
try {
|
||||||
return reqBuf;
|
KeyAlgorithm ka = params.getTransport().getKeyAlgorithm(keyType);
|
||||||
|
reqBuf.putString(ka.getKeyAlgorithm())
|
||||||
|
.putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
|
||||||
|
return reqBuf;
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UserAuthException("No KeyAlgorithm configured for key " + keyType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SSHPacket putSig(SSHPacket reqBuf)
|
protected SSHPacket putSig(SSHPacket reqBuf)
|
||||||
@@ -61,17 +68,20 @@ public abstract class KeyedAuthMethod
|
|||||||
throw new UserAuthException("Problem getting private key from " + kProv, ioe);
|
throw new UserAuthException("Problem getting private key from " + kProv, ioe);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String kt = KeyType.fromKey(key).toString();
|
final KeyType kt = KeyType.fromKey(key);
|
||||||
Signature signature = Factory.Named.Util.create(params.getTransport().getConfig().getSignatureFactories(), kt);
|
Signature signature;
|
||||||
if (signature == null)
|
try {
|
||||||
throw new UserAuthException("Could not create signature instance for " + kt + " key");
|
signature = params.getTransport().getKeyAlgorithm(kt).newSignature();
|
||||||
|
} catch (TransportException e) {
|
||||||
|
throw new UserAuthException("No KeyAlgorithm configured for key " + kt);
|
||||||
|
}
|
||||||
|
|
||||||
signature.initSign(key);
|
signature.initSign(key);
|
||||||
signature.update(new Buffer.PlainBuffer()
|
signature.update(new Buffer.PlainBuffer()
|
||||||
.putString(params.getTransport().getSessionID())
|
.putString(params.getTransport().getSessionID())
|
||||||
.putBuffer(reqBuf) // & rest of the data for sig
|
.putBuffer(reqBuf) // & rest of the data for sig
|
||||||
.getCompactData());
|
.getCompactData());
|
||||||
reqBuf.putSignature(kt, signature.encode(signature.sign()));
|
reqBuf.putSignature(signature.getSignatureName(), signature.encode(signature.sign()));
|
||||||
return reqBuf;
|
return reqBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ public class LoggingTransferListener
|
|||||||
public void reportProgress(long transferred)
|
public void reportProgress(long transferred)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
log.trace("transferred {}% of `{}`", ((transferred * 100) / size), path);
|
long percent = 100;
|
||||||
|
if (size > 0) {
|
||||||
|
percent = (transferred * 100)/size;
|
||||||
|
}
|
||||||
|
log.trace("transferred {}% of `{}`", percent, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.signature
|
package net.schmizz.sshj.signature
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm
|
||||||
import spock.lang.Unroll;
|
import spock.lang.Unroll;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@@ -47,7 +48,7 @@ import spock.lang.Specification
|
|||||||
|
|
||||||
class SignatureDSASpec extends Specification {
|
class SignatureDSASpec extends Specification {
|
||||||
|
|
||||||
def keyFactory = KeyFactory.getInstance("DSA")
|
def keyFactory = KeyFactory.getInstance(KeyAlgorithm.DSA)
|
||||||
|
|
||||||
private PublicKey createPublicKey(final byte[] y, final byte[] p, final byte[] q, final byte[] g) throws Exception {
|
private PublicKey createPublicKey(final byte[] y, final byte[] p, final byte[] q, final byte[] g) throws Exception {
|
||||||
final BigInteger publicKey = new BigInteger(y);
|
final BigInteger publicKey = new BigInteger(y);
|
||||||
|
|||||||
@@ -44,6 +44,6 @@ public class StreamCopierTest {
|
|||||||
long copied = streamCopier.copy();
|
long copied = streamCopier.copy();
|
||||||
assertThat(copied, is(1024L));
|
assertThat(copied, is(1024L));
|
||||||
|
|
||||||
verify(logger).debug(contains("1.0 KiB transferred"));
|
verify(logger).debug(matches("^1[.,]0 KiB transferred.*$"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.keyprovider;
|
package net.schmizz.sshj.keyprovider;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyDecryptionFailedException;
|
||||||
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
||||||
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
||||||
import net.schmizz.sshj.common.KeyType;
|
import net.schmizz.sshj.common.KeyType;
|
||||||
@@ -200,12 +201,34 @@ public class OpenSSHKeyFileTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldLoadProtectedED25519PrivateKeyAes256CTR() throws IOException {
|
public void shouldLoadProtectedED25519PrivateKeyAes256CTR() throws IOException {
|
||||||
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_protected", "sshjtest");
|
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_protected", "sshjtest", false);
|
||||||
|
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_protected", "sshjtest", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldLoadProtectedED25519PrivateKeyAes256CBC() throws IOException {
|
public void shouldLoadProtectedED25519PrivateKeyAes256CBC() throws IOException {
|
||||||
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_aes256cbc.pem", "foobar");
|
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_aes256cbc.pem", "foobar", false);
|
||||||
|
checkOpenSSHKeyV1("src/test/resources/keytypes/ed25519_aes256cbc.pem", "foobar", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = KeyDecryptionFailedException.class)
|
||||||
|
public void shouldFailOnIncorrectPassphraseAfterRetries() throws IOException {
|
||||||
|
OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile();
|
||||||
|
keyFile.init(new File("src/test/resources/keytypes/ed25519_aes256cbc.pem"), new PasswordFinder() {
|
||||||
|
private int reqCounter = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char[] reqPassword(Resource<?> resource) {
|
||||||
|
reqCounter++;
|
||||||
|
return "incorrect".toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRetry(Resource<?> resource) {
|
||||||
|
return reqCounter <= 3;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
keyFile.getPrivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -224,17 +247,25 @@ public class OpenSSHKeyFileTest {
|
|||||||
assertThat(aPrivate.getAlgorithm(), equalTo("ECDSA"));
|
assertThat(aPrivate.getAlgorithm(), equalTo("ECDSA"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkOpenSSHKeyV1(String key, final String password) throws IOException {
|
private void checkOpenSSHKeyV1(String key, final String password, boolean withRetry) throws IOException {
|
||||||
OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile();
|
OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile();
|
||||||
keyFile.init(new File(key), new PasswordFinder() {
|
keyFile.init(new File(key), new PasswordFinder() {
|
||||||
|
private int reqCounter = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] reqPassword(Resource<?> resource) {
|
public char[] reqPassword(Resource<?> resource) {
|
||||||
return password.toCharArray();
|
if (withRetry && reqCounter < 3) {
|
||||||
|
reqCounter++;
|
||||||
|
// Return an incorrect password three times before returning the correct one.
|
||||||
|
return (password + "incorrect").toCharArray();
|
||||||
|
} else {
|
||||||
|
return password.toCharArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRetry(Resource<?> resource) {
|
public boolean shouldRetry(Resource<?> resource) {
|
||||||
return false;
|
return withRetry && reqCounter <= 3;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
PrivateKey aPrivate = keyFile.getPrivate();
|
PrivateKey aPrivate = keyFile.getPrivate();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import java.security.spec.DSAPrivateKeySpec;
|
|||||||
import java.security.spec.DSAPublicKeySpec;
|
import java.security.spec.DSAPublicKeySpec;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -35,7 +36,7 @@ public class SignatureDSATest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws NoSuchAlgorithmException {
|
public void setUp() throws NoSuchAlgorithmException {
|
||||||
keyFactory = KeyFactory.getInstance("DSA");
|
keyFactory = KeyFactory.getInstance(KeyAlgorithm.DSA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.util;
|
package net.schmizz.sshj.util;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.common.KeyAlgorithm;
|
||||||
import net.schmizz.sshj.common.SecurityUtils;
|
import net.schmizz.sshj.common.SecurityUtils;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@@ -46,7 +47,7 @@ public class KeyUtil {
|
|||||||
/** Creates a DSA private key. */
|
/** Creates a DSA private key. */
|
||||||
public static PrivateKey newDSAPrivateKey(String x, String p, String q, String g)
|
public static PrivateKey newDSAPrivateKey(String x, String p, String q, String g)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
return SecurityUtils.getKeyFactory("DSA").generatePrivate(new DSAPrivateKeySpec(new BigInteger(x, 16),
|
return SecurityUtils.getKeyFactory(KeyAlgorithm.DSA).generatePrivate(new DSAPrivateKeySpec(new BigInteger(x, 16),
|
||||||
new BigInteger(p, 16),
|
new BigInteger(p, 16),
|
||||||
new BigInteger(q, 16),
|
new BigInteger(q, 16),
|
||||||
new BigInteger(g, 16))
|
new BigInteger(g, 16))
|
||||||
@@ -56,7 +57,7 @@ public class KeyUtil {
|
|||||||
/** Creates a DSA public key. */
|
/** Creates a DSA public key. */
|
||||||
public static PublicKey newDSAPublicKey(String y, String p, String q, String g)
|
public static PublicKey newDSAPublicKey(String y, String p, String q, String g)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
return SecurityUtils.getKeyFactory("DSA").generatePublic(new DSAPublicKeySpec(new BigInteger(y, 16),
|
return SecurityUtils.getKeyFactory(KeyAlgorithm.DSA).generatePublic(new DSAPublicKeySpec(new BigInteger(y, 16),
|
||||||
new BigInteger(p, 16),
|
new BigInteger(p, 16),
|
||||||
new BigInteger(q, 16),
|
new BigInteger(q, 16),
|
||||||
new BigInteger(g, 16))
|
new BigInteger(g, 16))
|
||||||
@@ -66,7 +67,7 @@ public class KeyUtil {
|
|||||||
/** Creates an RSA private key. */
|
/** Creates an RSA private key. */
|
||||||
public static PrivateKey newRSAPrivateKey(String modulus, String exponent)
|
public static PrivateKey newRSAPrivateKey(String modulus, String exponent)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
return SecurityUtils.getKeyFactory("RSA").generatePrivate(new RSAPrivateKeySpec(new BigInteger(modulus, 16),
|
return SecurityUtils.getKeyFactory(KeyAlgorithm.RSA).generatePrivate(new RSAPrivateKeySpec(new BigInteger(modulus, 16),
|
||||||
new BigInteger(exponent, 16))
|
new BigInteger(exponent, 16))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -74,7 +75,7 @@ public class KeyUtil {
|
|||||||
/** Creates an RSA public key. */
|
/** Creates an RSA public key. */
|
||||||
public static PublicKey newRSAPublicKey(String modulus, String exponent)
|
public static PublicKey newRSAPublicKey(String modulus, String exponent)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
return SecurityUtils.getKeyFactory("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(modulus, 16),
|
return SecurityUtils.getKeyFactory(KeyAlgorithm.RSA).generatePublic(new RSAPublicKeySpec(new BigInteger(modulus, 16),
|
||||||
new BigInteger(exponent, 16)));
|
new BigInteger(exponent, 16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user