@@ -59,13 +59,33 @@ 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 = javaClass.getResourceAsStream(" /keys/$resourcePath " )!!
79+ .bufferedReader()
80+ .readText()
81+ return PrivateKeyReader .read(data)
82+ }
83+
84+ private fun signWithSshAlgorithm (privateKey : SshPrivateKey , algorithmName : String , data : ByteArray ): ByteArray {
85+ val entry = SignatureEntry .fromSshName(algorithmName) ? : error(" Unknown algorithm: $algorithmName " )
86+ return entry.algorithm.sign(algorithmName, privateKey.jcaKeyPair.private, data)
87+ }
88+
6989 @Test
7090 fun `accepts rsa-sha2-256 signature when rsa-sha2-256 was negotiated` () {
7191 val kp = KeyPairGenerator .getInstance(" RSA" ).apply { initialize(2048 ) }.generateKeyPair()
@@ -132,4 +152,68 @@ class SignatureVerifierTest {
132152
133153 assertFalse(SignatureVerifier .verify(hostKey, sigBlob, data, " rsa-sha2-256" ))
134154 }
155+
156+ @Test
157+ fun `rejects negotiated unknown signature algorithm` () {
158+ val kp = KeyPairGenerator .getInstance(" RSA" ).apply { initialize(2048 ) }.generateKeyPair()
159+ val data = " exchange hash" .toByteArray()
160+ val hostKey = buildRsaHostKey(kp.public as RSAPublicKey )
161+ val sigBlob = buildSignatureBlob(" unknown-algo" , byteArrayOf(1 , 2 , 3 ))
162+
163+ assertFalse(SignatureVerifier .verify(hostKey, sigBlob, data, " unknown-algo" ))
164+ }
165+
166+ @Test
167+ fun `verifyWithKeyType accepts RSA-compatible signature algorithms` () {
168+ val privateKey = readKey(" rsa_unencrypted" )
169+ val data = " session binding" .toByteArray()
170+ val hostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
171+
172+ for (algorithmName in listOf (" ssh-rsa" , " rsa-sha2-256" , " rsa-sha2-512" )) {
173+ val sigBlob = signWithSshAlgorithm(privateKey, algorithmName, data)
174+
175+ assertTrue(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data), algorithmName)
176+ }
177+ }
178+
179+ @Test
180+ fun `verifyWithKeyType accepts matching Ed25519 signature algorithm` () {
181+ val privateKey = readKey(" ed25519_unencrypted" )
182+ val data = " session binding" .toByteArray()
183+ val hostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
184+ val sigBlob = signWithSshAlgorithm(privateKey, " ssh-ed25519" , data)
185+
186+ assertTrue(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data))
187+ }
188+
189+ @Test
190+ fun `verifyWithKeyType rejects signature algorithm incompatible with key type` () {
191+ val privateKey = readKey(" ed25519_unencrypted" )
192+ val rsaKey = readKey(" rsa_unencrypted" )
193+ val data = " session binding" .toByteArray()
194+ val ed25519HostKey = SshPublicKeyEncoder .encode(privateKey.jcaKeyPair, privateKey.keyType)
195+ val rsaSigBlob = signWithSshAlgorithm(rsaKey, " rsa-sha2-256" , data)
196+
197+ assertFalse(SignatureVerifier .verifyWithKeyType(ed25519HostKey, rsaSigBlob, data))
198+ }
199+
200+ @Test
201+ fun `verifyWithKeyType rejects non-RSA signature algorithm for RSA key` () {
202+ val rsaKey = readKey(" rsa_unencrypted" )
203+ val ed25519Key = readKey(" ed25519_unencrypted" )
204+ val data = " session binding" .toByteArray()
205+ val rsaHostKey = SshPublicKeyEncoder .encode(rsaKey.jcaKeyPair, rsaKey.keyType)
206+ val ed25519SigBlob = signWithSshAlgorithm(ed25519Key, " ssh-ed25519" , data)
207+
208+ assertFalse(SignatureVerifier .verifyWithKeyType(rsaHostKey, ed25519SigBlob, data))
209+ }
210+
211+ @Test
212+ fun `verifyWithKeyType rejects unknown self-described signature algorithm` () {
213+ val data = " session binding" .toByteArray()
214+ val hostKey = buildUnknownHostKey()
215+ val sigBlob = buildSignatureBlob(" unknown-key@example.com" , byteArrayOf(4 , 5 , 6 ))
216+
217+ assertFalse(SignatureVerifier .verifyWithKeyType(hostKey, sigBlob, data))
218+ }
135219}
0 commit comments