From 633b42fec81ad74cd8426f2304542f282e9343e3 Mon Sep 17 00:00:00 2001 From: Adam Iwaniuk <31616173+aiwaniuk@users.noreply.github.com> Date: Mon, 27 May 2019 10:46:01 +0200 Subject: [PATCH] Added support for RSA certificates as host key (#514) * Added support for RSA certificates as host key * removed not needed check * added rsa cert signature verification test --- .../java/net/schmizz/sshj/DefaultConfig.java | 1 + .../schmizz/sshj/signature/SignatureRSA.java | 45 ++++++++++++++-- .../sshj/signature/SignatureRSATest.java | 52 +++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 src/test/java/net/schmizz/sshj/signature/SignatureRSATest.java diff --git a/src/main/java/net/schmizz/sshj/DefaultConfig.java b/src/main/java/net/schmizz/sshj/DefaultConfig.java index 00eb5219..7f1bbf85 100644 --- a/src/main/java/net/schmizz/sshj/DefaultConfig.java +++ b/src/main/java/net/schmizz/sshj/DefaultConfig.java @@ -214,6 +214,7 @@ public class DefaultConfig new SignatureECDSA.Factory384(), new SignatureECDSA.Factory521(), new SignatureRSA.Factory(), + new SignatureRSA.FactoryCERT(), new SignatureDSA.Factory() ); } diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureRSA.java b/src/main/java/net/schmizz/sshj/signature/SignatureRSA.java index 16f33dbc..4fab9895 100644 --- a/src/main/java/net/schmizz/sshj/signature/SignatureRSA.java +++ b/src/main/java/net/schmizz/sshj/signature/SignatureRSA.java @@ -15,10 +15,14 @@ */ package net.schmizz.sshj.signature; +import com.hierynomus.sshj.userauth.certificate.Certificate; import net.schmizz.sshj.common.KeyType; import net.schmizz.sshj.common.SSHRuntimeException; +import java.security.InvalidKeyException; +import java.security.PublicKey; import java.security.SignatureException; +import java.util.Date; /** RSA {@link Signature} */ public class SignatureRSA @@ -30,7 +34,7 @@ public class SignatureRSA @Override public Signature create() { - return new SignatureRSA(); + return new SignatureRSA(KeyType.RSA.toString()); } @Override @@ -40,8 +44,42 @@ public class SignatureRSA } - public SignatureRSA() { + /** A named factory for RSA {@link Signature} */ + public static class FactoryCERT + implements net.schmizz.sshj.common.Factory.Named { + + @Override + public Signature create() { + return new SignatureRSA(KeyType.RSA_CERT.toString()); + } + + @Override + public String getName() { + return KeyType.RSA_CERT.toString(); + } + + } + + private String keyTypeName; + + + public SignatureRSA(String keyTypeName) { super("SHA1withRSA"); + this.keyTypeName = keyTypeName; + } + + @Override + @SuppressWarnings("unchecked") + public void initVerify(PublicKey publicKey) { + try { + if (this.keyTypeName.equals(KeyType.RSA_CERT.toString()) && publicKey instanceof Certificate) { + signature.initVerify(((Certificate) publicKey).getKey()); + } else { + signature.initVerify(publicKey); + } + } catch (InvalidKeyException e) { + throw new SSHRuntimeException(e); + } } @Override @@ -51,12 +89,11 @@ public class SignatureRSA @Override public boolean verify(byte[] sig) { - sig = extractSig(sig, "ssh-rsa"); + sig = extractSig(sig, KeyType.RSA.toString()); try { return signature.verify(sig); } catch (SignatureException e) { throw new SSHRuntimeException(e); } } - } diff --git a/src/test/java/net/schmizz/sshj/signature/SignatureRSATest.java b/src/test/java/net/schmizz/sshj/signature/SignatureRSATest.java new file mode 100644 index 00000000..f031c277 --- /dev/null +++ b/src/test/java/net/schmizz/sshj/signature/SignatureRSATest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C)2009 - SSHJ Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.schmizz.sshj.signature; + +import net.schmizz.sshj.common.Buffer; +import org.junit.Assert; +import org.junit.Test; + +import java.security.PublicKey; + + +public class SignatureRSATest { + + @Test + public void testRSACERTVerifies() throws Buffer.BufferException { + byte[] certBytes = fromString("0, 0, 0, 28, 115, 115, 104, 45, 114, 115, 97, 45, 99, 101, 114, 116, 45, 118, 48, 49, 64, 111, 112, 101, 110, 115, 115, 104, 46, 99, 111, 109, 0, 0, 0, 32, 111, 79, -117, -106, 111, -73, 4, -86, -70, -97, -106, 40, 49, -22, 72, -41, -14, 42, -89, -123, -89, 72, 86, 24, 110, -103, -67, 99, 72, -53, 108, -109, 0, 0, 0, 3, 1, 0, 1, 0, 0, 1, 1, 0, -59, -10, 91, 117, -120, 1, -103, 88, 106, -115, -76, -92, 116, -28, 116, 76, 75, 36, 82, 27, 105, 98, -48, 122, -69, -33, 101, 54, -55, 15, 76, -103, 100, -128, 19, 9, 109, 5, 114, 11, 9, 74, -45, -98, 66, 78, 88, -125, 24, -56, -90, 56, 99, 109, -118, -7, -94, 22, 50, 105, -55, 116, 79, 44, 122, 23, -39, -23, -33, -96, -49, 109, 50, 103, -55, 7, -99, -48, 123, 10, 114, -89, -22, -116, 97, -22, 69, -71, 52, 1, -78, 123, 121, 3, 71, -51, 60, 47, -51, -6, 83, 101, 113, 48, -56, 41, 76, 127, -27, 6, 46, 61, -45, -37, 74, 127, -85, -64, 99, 106, -88, 27, -14, -42, -31, -5, 69, 89, -57, -12, -115, 78, -44, -14, 92, 37, -68, -98, 38, -116, -97, 75, 119, -109, -101, 104, -109, -102, -42, 29, -44, 68, 117, -87, -119, 123, -110, 107, -14, 69, 85, 51, 21, 3, 63, 25, -18, 30, -95, 94, -100, 43, -70, -3, -121, 66, 82, -119, 26, -51, -102, -60, -2, -11, -92, 100, 122, 86, 120, -74, 124, 54, 120, -111, 105, -7, 116, -26, -17, -40, -32, 57, 84, -72, -109, 15, -26, 25, -75, 13, 30, 116, 1, 10, 57, 28, -124, 77, -96, -125, -62, 0, -96, 95, -118, -115, -63, -47, -124, -4, 13, -5, 115, 80, 122, 43, -85, 70, 102, -75, -122, -115, 118, -113, 0, 42, 78, 22, 60, 35, 85, 88, 68, 35, -60, -49, -128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 7, 116, 101, 115, 116, 114, 115, 97, 0, 0, 0, 20, 0, 0, 0, 6, 106, 101, 114, 111, 101, 110, 0, 0, 0, 6, 110, 111, 98, 111, 100, 121, 0, 0, 0, 0, 88, -19, 76, -72, 0, 0, 0, 0, 88, -19, 84, 23, 0, 0, 0, 0, 0, 0, 0, -126, 0, 0, 0, 21, 112, 101, 114, 109, 105, 116, 45, 88, 49, 49, 45, 102, 111, 114, 119, 97, 114, 100, 105, 110, 103, 0, 0, 0, 0, 0, 0, 0, 23, 112, 101, 114, 109, 105, 116, 45, 97, 103, 101, 110, 116, 45, 102, 111, 114, 119, 97, 114, 100, 105, 110, 103, 0, 0, 0, 0, 0, 0, 0, 22, 112, 101, 114, 109, 105, 116, 45, 112, 111, 114, 116, 45, 102, 111, 114, 119, 97, 114, 100, 105, 110, 103, 0, 0, 0, 0, 0, 0, 0, 10, 112, 101, 114, 109, 105, 116, 45, 112, 116, 121, 0, 0, 0, 0, 0, 0, 0, 14, 112, 101, 114, 109, 105, 116, 45, 117, 115, 101, 114, 45, 114, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 23, 0, 0, 0, 7, 115, 115, 104, 45, 114, 115, 97, 0, 0, 0, 3, 1, 0, 1, 0, 0, 1, 1, 0, -39, -47, -83, 61, 114, -97, -95, -80, -82, -59, -27, -24, 56, 122, -36, 30, -103, 108, -119, -116, 15, 123, 46, 84, -79, 2, -59, -114, -60, -45, 78, -78, 67, 98, -40, 80, -21, -123, -128, -87, 49, -24, -21, -42, -73, 107, 7, 92, -121, -53, 117, 24, -108, 109, 0, 27, 118, -26, -51, 125, 116, -69, 38, -99, -41, -65, -64, 30, 82, -81, 52, -60, 33, -22, -68, -84, 109, -18, -125, 14, 7, 79, 57, 84, 45, 102, -2, 84, 8, 43, -81, 60, 57, -25, 80, 9, -2, -7, 37, -22, -59, -122, -17, 84, 84, -118, -29, -64, 73, 93, -28, 100, -38, 98, -85, -100, 45, -94, 90, -55, -55, 9, 111, 53, -113, -46, 2, 3, 100, -72, 44, 75, 88, 19, 64, -30, 97, 26, -52, -39, 68, -3, -107, 72, 38, 115, 12, 75, 26, -94, -6, 38, 69, -101, 37, 49, 126, -28, -94, -14, 70, -13, -58, -75, -67, 58, 82, -114, 74, 57, -47, 101, -54, 49, 21, 103, -115, -5, -113, -4, 13, 78, -71, -10, -75, -76, 9, 104, -60, -7, -87, -93, 110, -121, -125, -14, -15, 101, 123, 104, 41, -41, -17, 118, 31, 36, 119, 107, -100, 38, -31, 56, -3, 76, 5, 127, 103, 79, -25, 105, 50, -62, -40, 94, 112, -94, -48, -81, -53, 44, 34, -119, 33, 105, -4, -56, -36, 49, 62, 106, -44, 115, 67, -92, -88, -26, 16, 89, -72, -58, -112, -87, -10, 118, -33, -9, 0, 0, 1, 15, 0, 0, 0, 7, 115, 115, 104, 45, 114, 115, 97, 0, 0, 1, 0, -46, -20, -128, -63, 96, -123, 52, 81, 25, 92, -69, -78, -41, -23, 112, 119, -43, 109, -128, 39, 2, -25, 65, -54, 51, 33, -14, -64, -84, -28, -56, -87, 67, 33, -69, 10, 108, 34, -36, 64, 110, -8, 127, 73, -61, 63, -73, 62, -14, 48, 5, 68, 44, 75, 125, -95, -103, -25, -108, -104, 94, 67, -24, 92, -61, -113, -88, 91, 37, -97, -74, 47, -119, -48, -69, -98, 82, -95, 23, 100, 59, 22, 3, -127, 119, 78, 18, -94, -72, -128, -66, 45, 76, -37, -127, 0, 19, -26, 61, 45, 76, -6, -119, -46, -60, -71, -24, 23, -73, 125, -100, -95, -69, -2, 126, -91, 74, 68, 22, 116, 87, -91, 41, 13, -50, 86, -25, -49, -6, -108, 57, 54, 96, -61, 78, 33, -76, 16, 55, 45, -8, 45, -3, 71, -88, -120, 113, 105, 96, -70, -90, 105, -45, -34, -77, -36, 103, 41, 111, 100, -114, -16, 63, -97, 3, 118, 18, 39, 90, -127, 21, 49, -106, -80, 103, 73, -76, 63, 45, -126, -40, -10, -5, -52, -20, 5, 99, -51, 103, 94, -25, 2, 29, 71, -62, 47, -123, 39, -128, -35, 80, 56, -72, 61, -1, 75, -16, 25, -103, -108, 86, 68, -25, 62, -58, -34, 31, -88, 28, 6, -124, 24, -23, 119, 99, 108, -16, 124, 28, -1, -38, -43, 72, 43, -37, 11, 19, -56, 82, 74, 117, -51, 126, -26, -65, -54, -75, -64, -117, -119, 119, -75, 74, 105, -121, 64"); + byte[] msg = fromString("116, 101, 115, 116, 10"); + byte[] sig = fromString("0, 0, 0, 7, 115, 115, 104, 45, 114, 115, 97, 0, 0, 1, 0, 121, 15, 34, -11, 125, 124, 91, 62, -47, 36, 77, -44, 13, -29, -36, -100, 65, -87, -67, -64, 11, 31, -24, -35, -53, 74, 18, 65, 12, 119, -33, -105, 65, 21, -55, -21, 89, 49, -97, -98, -48, 49, -20, -75, 88, 3, -84, 105, -51, -83, 92, 117, -118, -63, -5, -119, -69, -25, 22, -62, 83, -106, -112, -3, -104, -95, 89, -72, -59, -6, -18, 114, 113, 43, 32, 31, -11, 27, -39, -58, 75, -42, -30, -48, -81, 15, -92, 71, -85, -45, -101, 101, -60, 54, 7, -69, -120, -69, -3, 125, -52, -29, 44, 120, -50, -29, -38, -50, 7, 51, -68, -16, -87, -114, -105, 22, 31, 104, 110, 89, -50, -35, 124, 79, 26, 82, -26, 121, 47, 80, 26, -80, 65, 6, 35, -90, 87, -30, 63, -24, -82, -79, 79, -88, -26, 55, 120, 91, 119, 56, -26, 44, -106, -89, 118, -105, 88, -98, -46, -115, -6, -69, 121, -63, 100, -55, -126, -106, 79, -6, -56, 26, -26, 96, -113, -95, -121, -16, 44, -122, 6, 90, -56, -7, 99, 91, -67, 33, -53, -48, 63, 85, -29, 95, 35, 110, -89, 67, 84, -116, 85, -85, -21, -26, 19, 15, 36, 99, 22, 80, -99, -41, -119, 89, -36, -26, 113, -53, -39, 94, 74, 5, -96, -96, -121, -56, -61, 62, -14, 20, 69, 10, 80, -102, -68, -19, -59, 30, -76, -2, 89, -118, -48, 104, -46, 45, -63, 112, -110, 68, -108, 48, 61, 73, 103, 62"); + + PublicKey hostKey = new Buffer.PlainBuffer(certBytes).readPublicKey(); + + Signature signature = new SignatureRSA.FactoryCERT().create(); + signature.initVerify(hostKey); + signature.update(msg, 0, msg.length); + + Assert.assertTrue("RSACERT signature verifies", signature.verify(sig)); + } + + private byte[] fromString(String string) { + String[] split = string.split(", "); + byte[] res = new byte[split.length]; + + for (int i = 0; i < split.length; i++) + res[i] = Byte.parseByte(split[i]); + + return res; + } + +}