From 6b0ac338ca10fb8d159a7b8802f48252dfb5c71d Mon Sep 17 00:00:00 2001 From: Christian Hagau Date: Wed, 25 Apr 2018 00:00:00 +0000 Subject: [PATCH] Use correct signature format identifier when creating SSH signatures for RSA with SHA256 & SHA512 --- .../remote/SshAuthenticationService.java | 18 ++- .../ssh/signature/SshSignatureConverter.java | 36 ++++-- .../signature/SshSignatureConverterTest.java | 105 +++++++++++++++++- 3 files changed, 141 insertions(+), 18 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/SshAuthenticationService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/SshAuthenticationService.java index ce2f75246..2b3574aec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/SshAuthenticationService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/SshAuthenticationService.java @@ -194,10 +194,20 @@ public class SshAuthenticationService extends Service { byte[] rawSignature = authResult.getSignature(); byte[] sshSignature; try { - if (authSubKeyAlgorithm == PublicKeyAlgorithmTags.ECDSA) { - sshSignature = SshSignatureConverter.getSshSignatureEcDsa(rawSignature, authSubKeyCurveOid); - } else { - sshSignature = SshSignatureConverter.getSshSignature(rawSignature, authSubKeyAlgorithm); + switch (authSubKeyAlgorithm) { + case PublicKeyAlgorithmTags.ECDSA: + sshSignature = SshSignatureConverter.getSshSignatureEcDsa(rawSignature, authSubKeyCurveOid); + break; + case PublicKeyAlgorithmTags.RSA_SIGN: + case PublicKeyAlgorithmTags.RSA_GENERAL: + sshSignature = SshSignatureConverter.getSshSignatureRsa(rawSignature, hashAlgorithmTag); + break; + case PublicKeyAlgorithmTags.DSA: + case PublicKeyAlgorithmTags.EDDSA: + sshSignature = SshSignatureConverter.getSshSignature(rawSignature, authSubKeyAlgorithm); + break; + default: + throw new NoSuchAlgorithmException("Unknown algorithm"); } } catch (NoSuchAlgorithmException e) { return createExceptionErrorResult(SshAuthenticationApiError.INTERNAL_ERROR, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverter.java index 15ffdd2ed..b840f9e00 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverter.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ssh.signature; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.util.BigIntegers; import org.sufficientlysecure.keychain.ssh.key.SshEncodedData; @@ -31,12 +32,25 @@ import java.security.NoSuchAlgorithmException; public class SshSignatureConverter { - private static String getSignatureType(int algorithm) throws NoSuchAlgorithmException { - switch (algorithm) { - case PublicKeyAlgorithmTags.RSA_SIGN: - case PublicKeyAlgorithmTags.RSA_GENERAL: + private static String getRsaSignatureFormatId(int hashAlgorithm) throws NoSuchAlgorithmException { + // https://tools.ietf.org/html/rfc8332 + switch (hashAlgorithm) { + case HashAlgorithmTags.SHA512: + return "rsa-sha2-512"; + + case HashAlgorithmTags.SHA256: + return "rsa-sha2-256"; + + case HashAlgorithmTags.SHA1: return "ssh-rsa"; + default: + throw new NoSuchAlgorithmException("Unknown hash algorithm"); + } + } + + private static String getSignatureFormatId(int algorithm) throws NoSuchAlgorithmException { + switch (algorithm) { case PublicKeyAlgorithmTags.EDDSA: return "ssh-ed25519"; @@ -50,10 +64,6 @@ public class SshSignatureConverter { private static byte[] getSignatureBlob(byte[] rawSignature, int algorithm) throws NoSuchAlgorithmException { switch (algorithm) { - case PublicKeyAlgorithmTags.RSA_SIGN: - case PublicKeyAlgorithmTags.RSA_GENERAL: - return rawSignature; - case PublicKeyAlgorithmTags.EDDSA: return rawSignature; @@ -122,12 +132,20 @@ public class SshSignatureConverter { public static byte[] getSshSignature(byte[] rawSignature, int algorithm) throws NoSuchAlgorithmException { SshEncodedData signature = new SshEncodedData(); - signature.putString(getSignatureType(algorithm)); + signature.putString(getSignatureFormatId(algorithm)); signature.putString(getSignatureBlob(rawSignature, algorithm)); return signature.getBytes(); } + public static byte[] getSshSignatureRsa(byte[] rawSignature, int hashAlgorithm) throws NoSuchAlgorithmException { + SshEncodedData signature = new SshEncodedData(); + signature.putString(getRsaSignatureFormatId(hashAlgorithm)); + signature.putString(rawSignature); + + return signature.getBytes(); + } + public static byte[] getSshSignatureEcDsa(byte[] rawSignature, String curveOid) throws NoSuchAlgorithmException { SshEncodedData signature = new SshEncodedData(); signature.putString("ecdsa-sha2-" + SshUtils.getCurveName(curveOid)); diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverterTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverterTest.java index c0e3d7fed..c4d3c722f 100644 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverterTest.java +++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/ssh/signature/SshSignatureConverterTest.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ssh.signature; +import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; @@ -53,7 +54,87 @@ public class SshSignatureConverterTest { "7cff82ac2664b6419ff66f6e8b9669a0" ); - private final static byte[] RAW_RSA_SIGNATURE = Hex.decode( + private final static byte[] RAW_RSA_SIGNATURE_SHA512 = Hex.decode( + "4aef4be2d8edaed6faf2798c28685970" + + "ef19528e534ab3961d4e1b86ce5cf52a" + + "2bc7008d5e6738783d799779daf23714" + + "d688761ddf537eae9edab5a3a6b4e913" + + "04b7c2ed434c0a9ebbe3ea747a8c9b89" + + "e1cfc44007c1a12a6f4401e951c4b1ac" + + "9add2f49251f12effa31540448d12fec" + + "70188e4844597d73af3fbf9cca65d182" + + "1809f4c41a453e01a2f86bedcc691ec0" + + "831ec0fa6af47927f60b2559c2d95235" + + "0ad91d12cd94acb44f33e6039de00368" + + "8a729ccc045a367108af4fa89d8ae049" + + "e5c75872ee6ff30d7edf7fea2fcf7fca" + + "88aab94388b752abbab04b937ad77282" + + "a8a15c20005cf24f4b5d9174955a7e86" + + "6214a25f7f66d39ef31a6503da43d5dc" + ); + + private final static byte[] SSH_RSA_SIGNATURE_SHA512 = Hex.decode( + "0000000c7273612d736861322d353132" + + "000001004aef4be2d8edaed6faf2798c" + + "28685970ef19528e534ab3961d4e1b86" + + "ce5cf52a2bc7008d5e6738783d799779" + + "daf23714d688761ddf537eae9edab5a3" + + "a6b4e91304b7c2ed434c0a9ebbe3ea74" + + "7a8c9b89e1cfc44007c1a12a6f4401e9" + + "51c4b1ac9add2f49251f12effa315404" + + "48d12fec70188e4844597d73af3fbf9c" + + "ca65d1821809f4c41a453e01a2f86bed" + + "cc691ec0831ec0fa6af47927f60b2559" + + "c2d952350ad91d12cd94acb44f33e603" + + "9de003688a729ccc045a367108af4fa8" + + "9d8ae049e5c75872ee6ff30d7edf7fea" + + "2fcf7fca88aab94388b752abbab04b93" + + "7ad77282a8a15c20005cf24f4b5d9174" + + "955a7e866214a25f7f66d39ef31a6503" + + "da43d5dc" + ); + + private final static byte[] RAW_RSA_SIGNATURE_SHA256 = Hex.decode( + "904abb6965d075584d03e3d31aec58bc" + + "3738388b199c6aef55ec7e7f18daeaff" + + "6ff41d0e5dbd47c3a4cceb4a59d24cdb" + + "3d0041bc64324ae9e955232fb788f180" + + "ed885814760e18f73572cdf15a0fcc3b" + + "05c534e110e75a2093d27c96a8d122f3" + + "b30590003c5d90fd8029ab940d4ce3cf" + + "6cdeac92490cc0c93fbc9998e1d1fd31" + + "b2478f8cdf0e3af80a570212aa06bc7d" + + "d92af482e8826bae92bb4df637d073bd" + + "75647911981051d8e146a2ceffa86f02" + + "3ccd5746525e9599f215bcd3940e980a" + + "9190b435bd308b464e9799f3c186beee" + + "d5536f577e21177405059ebc2fe7bb43" + + "d014a96bd1221fbc821a7f5fda223d5d" + + "1be231260b237f88ef89738891e7c768" + ); + + private final static byte[] SSH_RSA_SIGNATURE_SHA256 = Hex.decode( + "0000000c7273612d736861322d323536" + + "00000100904abb6965d075584d03e3d3" + + "1aec58bc3738388b199c6aef55ec7e7f" + + "18daeaff6ff41d0e5dbd47c3a4cceb4a" + + "59d24cdb3d0041bc64324ae9e955232f" + + "b788f180ed885814760e18f73572cdf1" + + "5a0fcc3b05c534e110e75a2093d27c96" + + "a8d122f3b30590003c5d90fd8029ab94" + + "0d4ce3cf6cdeac92490cc0c93fbc9998" + + "e1d1fd31b2478f8cdf0e3af80a570212" + + "aa06bc7dd92af482e8826bae92bb4df6" + + "37d073bd75647911981051d8e146a2ce" + + "ffa86f023ccd5746525e9599f215bcd3" + + "940e980a9190b435bd308b464e9799f3" + + "c186beeed5536f577e21177405059ebc" + + "2fe7bb43d014a96bd1221fbc821a7f5f" + + "da223d5d1be231260b237f88ef897388" + + "91e7c768" + ); + + private final static byte[] RAW_RSA_SIGNATURE_SHA1 = Hex.decode( "1c975c37a4137e9c861d20d9d40b6db16d" + "1da8b17e360311b6a4ebcb3f1ff51d4906" + "28b80de0dece08a1b5ebe8a5894ea2fea7" + @@ -72,7 +153,7 @@ public class SshSignatureConverterTest { "19" ); - private final static byte[] SSH_RSA_SIGNATURE = Hex.decode( + private final static byte[] SSH_RSA_SIGNATURE_SHA1 = Hex.decode( "00000007" + "7373682d727361" + "00000100" + @@ -139,10 +220,24 @@ public class SshSignatureConverterTest { } @Test - public void testRsa() throws Exception { - byte[] out = SshSignatureConverter.getSshSignature(RAW_RSA_SIGNATURE, PublicKeyAlgorithmTags.RSA_SIGN); + public void testRsaSha1() throws Exception { + byte[] out = SshSignatureConverter.getSshSignatureRsa(RAW_RSA_SIGNATURE_SHA1, HashAlgorithmTags.SHA1); - Assert.assertArrayEquals(SSH_RSA_SIGNATURE, out); + Assert.assertArrayEquals(SSH_RSA_SIGNATURE_SHA1, out); + } + + @Test + public void testRsaSha256() throws Exception { + byte[] out = SshSignatureConverter.getSshSignatureRsa(RAW_RSA_SIGNATURE_SHA256, HashAlgorithmTags.SHA256); + + Assert.assertArrayEquals(SSH_RSA_SIGNATURE_SHA256, out); + } + + @Test + public void testRsaSha512() throws Exception { + byte[] out = SshSignatureConverter.getSshSignatureRsa(RAW_RSA_SIGNATURE_SHA512, HashAlgorithmTags.SHA512); + + Assert.assertArrayEquals(SSH_RSA_SIGNATURE_SHA512, out); } @Test