diff --git a/CHANGELOG.md b/CHANGELOG.md index cedebcef1..bda92745a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ Changes for library users since `0.6.3`. +### Fixed + +- ECDSA host keys and NIST ECDH key exchange no longer fail with + `NoSuchMethodError` on Android 12 and older: EC points are decoded without + `BigInteger(int, byte[], int, int)`, which Android has only since API 33. + The failure killed the app when the server sent its host keys after login. + ## [0.6.3][0.6.3] Changes for library users since `0.6.2`. diff --git a/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdhKeyExchange.kt b/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdhKeyExchange.kt index 5938cab52..4346a01cd 100644 --- a/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdhKeyExchange.kt +++ b/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdhKeyExchange.kt @@ -154,8 +154,9 @@ internal class EcdhKeyExchange(private val curveName: String) : KexAlgorithm { if (encoded.isEmpty() || encoded[0] != 0x04.toByte() || encoded.size != 1 + 2 * fieldSize) { throw SshException("Invalid EC point encoding") } - val x = BigInteger(1, encoded, 1, fieldSize) - val y = BigInteger(1, encoded, 1 + fieldSize, fieldSize) + // BigInteger(int, byte[], int, int) is missing before Android 13 (API 33). + val x = BigInteger(1, encoded.copyOfRange(1, 1 + fieldSize)) + val y = BigInteger(1, encoded.copyOfRange(1 + fieldSize, encoded.size)) val p = (ecParameterSpec.curve.field as ECFieldFp).p if (x >= p || y >= p || y.multiply(y).mod(p) != x.multiply(x).multiply(x).add(ecParameterSpec.curve.a.multiply(x)).add(ecParameterSpec.curve.b).mod(p) diff --git a/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdsaSignatureAlgorithm.kt b/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdsaSignatureAlgorithm.kt index 36892ad21..973a0e9c4 100644 --- a/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdsaSignatureAlgorithm.kt +++ b/sshlib/src/main/kotlin/org/connectbot/sshlib/crypto/EcdsaSignatureAlgorithm.kt @@ -69,8 +69,9 @@ internal object EcdsaSignatureAlgorithm : SshSignatureAlgorithm { if (encoded[0] != 0x04.toByte() || encoded.size != 1 + 2 * fieldSize) { throw SshException("Invalid EC point encoding") } - val x = BigInteger(1, encoded, 1, fieldSize) - val y = BigInteger(1, encoded, 1 + fieldSize, fieldSize) + // BigInteger(int, byte[], int, int) is missing before Android 13 (API 33). + val x = BigInteger(1, encoded.copyOfRange(1, 1 + fieldSize)) + val y = BigInteger(1, encoded.copyOfRange(1 + fieldSize, encoded.size)) return ECPoint(x, y) }