diff --git a/src/hex_core.app.src b/src/hex_core.app.src index f2dcd637..e967dc20 100644 --- a/src/hex_core.app.src +++ b/src/hex_core.app.src @@ -2,7 +2,7 @@ {description, "Reference implementation of Hex specifications"}, {vsn, "0.15.0"}, {registered, []}, - {applications, [kernel, stdlib, inets, ssl]}, + {applications, [kernel, stdlib, inets, ssl, ssh]}, {licenses, ["Apache-2.0"]}, {include_paths, ["CHANGELOG.md"]}, {exclude_paths, ["src/safe_erl_term.erl"]}, diff --git a/src/hex_repo.erl b/src/hex_repo.erl index 692c14a5..a69488ab 100644 --- a/src/hex_repo.erl +++ b/src/hex_repo.erl @@ -240,18 +240,20 @@ fingerprint(PublicKeyPem) when is_binary(PublicKeyPem) -> %% true %% ''' %% @end --spec fingerprint_equal(binary(), string()) -> boolean(). +-spec fingerprint_equal(binary(), iodata()) -> boolean(). fingerprint_equal(PublicKeyPem, ExpectedFingerprint) when is_binary(PublicKeyPem) -> ActualFingerprint = fingerprint(PublicKeyPem), constant_time_compare( list_to_binary(ActualFingerprint), - list_to_binary(ExpectedFingerprint) + iolist_to_binary(ExpectedFingerprint) ). %% @private %% Constant-time comparison to prevent timing attacks. %% Uses crypto:hash_equals/2 on OTP 25+, falls back to manual comparison on older versions. -if(?OTP_RELEASE >= 25). +constant_time_compare(A, B) when byte_size(A) =/= byte_size(B) -> + false; constant_time_compare(A, B) -> crypto:hash_equals(A, B). -else. diff --git a/test/hex_repo_SUITE.erl b/test/hex_repo_SUITE.erl index 551aaeba..7838d6a0 100644 --- a/test/hex_repo_SUITE.erl +++ b/test/hex_repo_SUITE.erl @@ -165,7 +165,9 @@ fingerprint_equal_test(_Config) -> "-----END PUBLIC KEY-----\n" >>, CorrectFingerprint = "SHA256:O1LOYhHFW4kcrblKAxROaDEzLD8bn1seWbe5tq8TRsk", - WrongFingerprint = "SHA256:WrongFingerprint123456789012345678901234567", + WrongFingerprint = <<"SHA256:WrongFingerprint123456789012345678901234567">>, + DifferentLengthFingerprint = "SHA256:TooShort", ?assert(hex_repo:fingerprint_equal(PublicKeyPem, CorrectFingerprint)), ?assertNot(hex_repo:fingerprint_equal(PublicKeyPem, WrongFingerprint)), + ?assertNot(hex_repo:fingerprint_equal(PublicKeyPem, DifferentLengthFingerprint)), ok.