@@ -59,13 +59,35 @@ class SignatureVerifierTest {
5959 return buf.toByteArray()
6060 }
6161
62+ private fun buildUnknownHostKey (algorithmName : String = "unknown-key@example.com"): ByteArray {
63+ val buf = ByteArrayOutputStream ()
64+ val out = DataOutputStream (buf)
65+ encodeString(out , algorithmName)
66+ encodeString(out , byteArrayOf(1 , 2 , 3 ))
67+ return buf.toByteArray()
68+ }
69+
6270 private fun signData (data : ByteArray , jcaAlgorithm : String , kp : java.security.KeyPair ): ByteArray {
6371 val sig = Signature .getInstance(jcaAlgorithm)
6472 sig.initSign(kp.private)
6573 sig.update(data)
6674 return sig.sign()
6775 }
6876
77+ private fun readKey (resourcePath : String ): SshPrivateKey {
78+ val data = requireNotNull(javaClass.getResourceAsStream(" /keys/$resourcePath " )) {
79+ " Missing test key resource: /keys/$resourcePath "
80+ }.use { stream ->
81+ stream.bufferedReader().use { reader -> reader.readText() }
82+ }
83+ return PrivateKeyReader .read(data)
84+ }
85+
86+ private fun signWithSshAlgorithm (privateKey : SshPrivateKey , algorithmName : String , data : ByteArray ): ByteArray {
87+ val entry = SignatureEntry .fromSshName(algorithmName) ? : error(" Unknown algorithm: $algorithmName " )
88+ return entry.algorithm.sign(algorithmName, privateKey.jcaKeyPair.private, data)
89+ }
90+
6991 @Test
7092 fun `accepts rsa-sha2-256 signature when rsa-sha2-256 was negotiated` () {
7193 val kp = KeyPairGenerator .getInstance(" RSA" ).apply { initialize(2048 ) }.generateKeyPair()
@@ -132,4 +154,68 @@ class SignatureVerifierTest {
132154
133155 assertFalse(SignatureVerifier .verify(hostKey, sigBlob, data, " rsa-sha2-256" ))
134156 }
157+
158+ @Test
159+ fun `rejects negotiated unknown signature algorithm` () {
160+ val kp = KeyPairGenerator .getInstance(" RSA" ).apply { initialize(2048 ) }.generateKeyPair()
161+ val data = " exchange hash" .toByteArray()
162+ val hostKey = buildRsaHostKey(kp.public as RSAPublicKey )
163+ val sigBlob = buildSignatureBlob(" unknown-algo" , byteArrayOf(1 , 2 , 3 ))
164+
165+ assertFalse(SignatureVerifier .verify(hostKey, sigBlob, data, " unknown-algo" ))
166+ }
167+
168+ @Test
169+ fun `verifyWithKeyType accepts RSA-compatible signature algorithms` () {
170+ val privateKey = readKey(" rsa_unencrypted" )
171+ val data = " session binding" .toByteArray()
172+ val hostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
173+
174+ for (algorithmName in listOf (" ssh-rsa" , " rsa-sha2-256" , " rsa-sha2-512" )) {
175+ val sigBlob = signWithSshAlgorithm(privateKey, algorithmName, data)
176+
177+ assertTrue(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data), algorithmName)
178+ }
179+ }
180+
181+ @Test
182+ fun `verifyWithKeyType accepts matching Ed25519 signature algorithm` () {
183+ val privateKey = readKey(" ed25519_unencrypted" )
184+ val data = " session binding" .toByteArray()
185+ val hostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
186+ val sigBlob = signWithSshAlgorithm(privateKey, " ssh-ed25519" , data)
187+
188+ assertTrue(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data))
189+ }
190+
191+ @Test
192+ fun `verifyWithKeyType rejects signature algorithm incompatible with key type` () {
193+ val privateKey = readKey(" ed25519_unencrypted" )
194+ val rsaKey = readKey(" rsa_unencrypted" )
195+ val data = " session binding" .toByteArray()
196+ val ed25519HostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
197+ val rsaSigBlob = signWithSshAlgorithm(rsaKey, " rsa-sha2-256" , data)
198+
199+ assertFalse(SignatureVerifier .verifyWithKeyType(ed25519HostKey, rsaSigBlob, data))
200+ }
201+
202+ @Test
203+ fun `verifyWithKeyType rejects non-RSA signature algorithm for RSA key` () {
204+ val rsaKey = readKey(" rsa_unencrypted" )
205+ val ed25519Key = readKey(" ed25519_unencrypted" )
206+ val data = " session binding" .toByteArray()
207+ val rsaHostKey = SshPublicKeyEncoder .encode(rsaKey.jcaKeyPair, rsaKey.keyType)
208+ val ed25519SigBlob = signWithSshAlgorithm(ed25519Key, " ssh-ed25519" , data)
209+
210+ assertFalse(SignatureVerifier .verifyWithKeyType(rsaHostKey, ed25519SigBlob, data))
211+ }
212+
213+ @Test
214+ fun `verifyWithKeyType rejects unknown self-described signature algorithm` () {
215+ val data = " session binding" .toByteArray()
216+ val hostKey = buildUnknownHostKey()
217+ val sigBlob = buildSignatureBlob(" unknown-key@example.com" , byteArrayOf(4 , 5 , 6 ))
218+
219+ assertFalse(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data))
220+ }
135221}
0 commit comments