RSA attack tool (mainly for ctf) - retrieve private key from weak public key and/or uncipher data
This report summarizes scanner evidence for RsaCtfTool/RsaCtfTool, a Python project with 7,174 GitHub stars. SynthScan examined 17,096 lines of code across 129 source files, recording 352 pattern matches distributed across 14 syntactic categories. The legacy adjusted pattern signal is 25.0 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 297 finding(s).
Are imports declared and package/API names verified? 3 finding(s).
Are wrappers, guards, and repeated structures necessary? 298 finding(s).
Which changes need focused human review? 352 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 352 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_number_theory.py | 82 | def test_isqrt_perfect_squares(self): | CODE |
| LOW | tests/test_number_theory.py | 150 | def test_next_prime_consecutive(self): | CODE |
| LOW | tests/test_number_theory.py | 165 | def test_powmod_large_exponent(self): | CODE |
| LOW | tests/test_number_theory.py | 257 | def test_chinese_remainder_basic(self): | CODE |
| LOW | tests/test_number_theory.py | 261 | def test_chinese_remainder_same_modulus(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 282 | def test_contfrac_to_rational_basic(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 286 | def test_contfrac_to_rational_empty(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 290 | def test_contfrac_to_rational_multiple_terms(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 309 | def test_convergents_multiple_terms(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 319 | def test_convergents_single_term(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 326 | def test_legendre_quadratic_residue(self): | CODE |
| LOW⚡ | tests/test_number_theory.py | 331 | def test_legendre_quadratic_non_residue(self): | CODE |
| LOW | tests/test_number_theory.py | 459 | def test_common_modulus_attack(self): | CODE |
| LOW | tests/test_number_theory.py | 542 | def test_isqrt_rem_perfect_square(self): | CODE |
| LOW | tests/test_number_theory.py | 547 | def test_isqrt_rem_non_perfect(self): | CODE |
| LOW | tests/test_number_theory.py | 575 | def test_miller_rabin_composite(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 17 | def test_coefficients_are_reduced_modulo_modulus(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 22 | def test_trailing_zeroes_are_removed(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 27 | def test_zero_polynomial_is_canonical(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 89 | def test_addition_with_scalar(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 95 | def test_addition_with_different_moduli_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 102 | def test_addition_with_invalid_operand_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 118 | def test_subtraction_is_modular(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 124 | def test_subtraction_with_scalar(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 130 | def test_subtraction_with_different_moduli_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 137 | def test_subtraction_with_invalid_operand_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 153 | def test_multiplication_with_scalar(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 159 | def test_multiplication_is_modular(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 165 | def test_multiplication_with_different_moduli_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 172 | def test_multiplication_with_invalid_operand_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 237 | def test_floor_division_returns_quotient(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 246 | def test_modulo_returns_remainder(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 255 | def test_division_by_zero_fails(self): | CODE |
| LOW⚡ | tests/test_polynomial.py | 261 | def test_noninvertible_leading_coefficient_fails(self): | CODE |
| LOW | tests/test_polynomial.py | 39 | def test_invalid_modulus_fails(self): | CODE |
| LOW | tests/test_polynomial.py | 53 | def test_different_coefficients_are_not_equal(self): | CODE |
| LOW | tests/test_polynomial.py | 56 | def test_different_moduli_are_not_equal(self): | CODE |
| LOW | tests/test_polynomial.py | 197 | def test_power_large_exponent(self): | CODE |
| LOW | tests/test_polynomial.py | 205 | def test_negative_power_fails(self): | CODE |
| LOW | tests/test_polynomial.py | 225 | def test_division_with_remainder(self): | CODE |
| LOW | tests/test_polynomial.py | 278 | def test_monic_zero_polynomial(self): | CODE |
| LOW | tests/test_polynomial.py | 306 | def test_gcd_of_coprime_polynomials(self): | CODE |
| LOW | tests/test_polynomial.py | 322 | def test_evaluation_is_modular(self): | CODE |
| LOW | tests/test_polynomial.py | 338 | def test_multiplicative_identity(self): | CODE |
| LOW | tests/test_polynomial.py | 344 | def test_division_reconstruction(self): | CODE |
| LOW | tests/test_polynomial.py | 355 | def test_affine_polynomial_construction(self): | CODE |
| LOW | tests/test_abstract_attack.py | 19 | def test_create_private_key_returns_key_for_valid_factors(self, valid_public_key): | CODE |
| LOW | tests/test_abstract_attack.py | 26 | def test_create_private_key_rejects_malformed_values(self, valid_public_key): | CODE |
| LOW | tests/test_abstract_attack.py | 39 | def test_create_private_key_from_pqe_rejects_malformed_values(self, p, q, e, n): | CODE |
| LOW | tests/test_abstract_attack.py | 42 | def test_helpers_reject_invalid_factor_split(self, valid_public_key): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 80 | def test_small_composites_false(self, n): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 83 | def test_ilogb_big_int_no_overflow(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 91 | def test_pollard_rho_never_trivial(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 98 | def test_lehman_valid_or_none(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 143 | def test_derives_missing_prime(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 149 | def test_rejects_non_dividing_prime(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 155 | def test_rejects_missing_primes(self): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 233 | def test_api_key_enables_only_with_package(self, monkeypatch): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 243 | def test_missing_api_key_disables(self, monkeypatch): | CODE |
| LOW⚡ | tests/test_audit_regressions.py | 253 | def test_conspicuous_accepts_phi_inverse(self): | CODE |
| 185 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/RsaCtfTool/main.py | 332 | CODE | |
| LOW | src/RsaCtfTool/main.py | 348 | CODE | |
| LOW | src/RsaCtfTool/main.py | 478 | CODE | |
| LOW | src/RsaCtfTool/main.py | 628 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 55 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 103 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 174 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 194 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 259 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 353 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 644 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 776 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 794 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 923 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 976 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1085 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1130 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1201 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1355 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1408 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1427 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 700 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1444 | CODE | |
| LOW | src/RsaCtfTool/lib/algos.py | 1466 | CODE | |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 56 | CODE | |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 129 | CODE | |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 169 | CODE | |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 182 | CODE | |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 260 | CODE | |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 18 | CODE | |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 241 | CODE | |
| LOW | src/RsaCtfTool/lib/utils.py | 63 | CODE | |
| LOW | src/RsaCtfTool/lib/utils.py | 86 | CODE | |
| LOW | src/RsaCtfTool/lib/utils.py | 128 | CODE | |
| LOW | src/RsaCtfTool/sage/roca_attack.py | 50 | CODE | |
| LOW | src/RsaCtfTool/attacks/single_key/wolframalpha.py | 36 | CODE | |
| LOW | …Tool/attacks/single_key/multiple_base_inversion_gcd.py | 47 | CODE | |
| LOW | src/RsaCtfTool/attacks/single_key/ecm2.py | 21 | CODE | |
| LOW | src/RsaCtfTool/attacks/single_key/nonRSA.py | 14 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/RsaCtfTool/lib/keys_wrapper.py | 73 | except (ValueError, TypeError): | CODE |
| HIGH | src/RsaCtfTool/lib/keys_wrapper.py | 267 | except Exception: | CODE |
| HIGH | src/RsaCtfTool/lib/keys_wrapper.py | 279 | except Exception: | CODE |
| HIGH | src/RsaCtfTool/lib/polynomial.py | 66 | except (ValueError, TypeError): | CODE |
| HIGH | src/RsaCtfTool/attacks/single_key/ecm.py | 76 | except KeyboardInterrupt: | CODE |
| HIGH | src/RsaCtfTool/attacks/single_key/partial_d.py | 51 | except ValueError: | CODE |
| HIGH | src/RsaCtfTool/attacks/single_key/ecm2.py | 79 | except KeyboardInterrupt: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_regression.py | 18 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_regression.py | 21 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_regression.py | 68 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_regression.py | 70 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_regression.py | 128 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_regression.py | 130 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_regression.py | 266 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_regression.py | 269 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docs/failure_modes.md | 69 | except Exception: | CODE |
| LOW | src/RsaCtfTool/main.py | 262 | except Exception as exc: | STRING |
| LOW | src/RsaCtfTool/main.py | 366 | except Exception: | STRING |
| LOW | src/RsaCtfTool/main.py | 587 | except Exception: | STRING |
| MEDIUM | src/RsaCtfTool/main.py | 254 | def run_conspicuous_check(args, logger): | CODE |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 195 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 247 | except Exception as e: | CODE |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 279 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 297 | except Exception as e: | CODE |
| LOW | src/RsaCtfTool/lib/rsa_attack.py | 406 | except Exception as e: | CODE |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 88 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 169 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 256 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 267 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 279 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/utils.py | 42 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/utils.py | 72 | except Exception: | CODE |
| LOW | src/RsaCtfTool/lib/utils.py | 145 | except Exception: | CODE |
| LOW | src/RsaCtfTool/sage/roca_attack.py | 128 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/wolframalpha.py | 66 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/wolframalpha.py | 100 | except Exception as e: | CODE |
| LOW | …Tool/attacks/single_key/multiple_base_inversion_gcd.py | 61 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/factordb.py | 51 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/factor_2PN.py | 23 | except Exception: | CODE |
| LOW | …c/RsaCtfTool/attacks/single_key/highandlowbitsequal.py | 19 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/SQUFOF.py | 19 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/z3_solver.py | 56 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/z3_solver.py | 63 | except Exception: | CODE |
| LOW | src/RsaCtfTool/attacks/single_key/euler.py | 27 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/RsaCtfTool/attacks/single_key/fermat.py | 0 | -----begin public key----- migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqcg6zybpnfefpkadglb1idarrl3 gk+vs1csgk1cy3kspypfydlvv7ak | STRING |
| HIGH | src/RsaCtfTool/attacks/single_key/kraitchik.py | 0 | -----begin public key----- migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqcg6zybpnfefpkadglb1idarrl3 gk+vs1csgk1cy3kspypfydlvv7ak | STRING |
| HIGH | src/RsaCtfTool/attacks/single_key/lehmer.py | 0 | -----begin public key----- migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqcg6zybpnfefpkadglb1idarrl3 gk+vs1csgk1cy3kspypfydlvv7ak | STRING |
| HIGH | src/RsaCtfTool/attacks/single_key/lehman.py | 0 | -----begin public key----- migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqcg6zybpnfefpkadglb1idarrl3 gk+vs1csgk1cy3kspypfydlvv7ak | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/RsaCtfTool/lib/coppersmith.py | 73 | Find small integer roots of a monic univariate polynomial modulo N. Sage is intentionally not imported here. | STRING |
| HIGH | src/RsaCtfTool/sage/coppersmith.py | 21 | Sage backend for univariate Coppersmith/Howgrave-Graham. Args: polynomial: Monic univariate Sage polyn | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | src/RsaCtfTool/lib/algos.py | 145 | # Create a look-up table | COMMENT |
| MEDIUM | src/RsaCtfTool/sage/roca_attack.py | 87 | # Create the polynom f(x) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | optional-requirements.txt | 1 | # Optional pip packages enabling extra attack modules | COMMENT |
| LOW | docs/failure_modes.md | 161 | ### 20. Recursion depth in continued fraction computation | COMMENT |
| LOW | docs/failure_modes.md | 181 | ### 30. `PrivateKey._init_fields` truncates arbitrary `d` to `int` via `self.d = d` with no type check | COMMENT |
| LOW | src/RsaCtfTool/lib/coppersmith.py | 161 | # | COMMENT |
| LOW | src/RsaCtfTool/attacks/single_key/siqs.py | 1 | #!/usr/bin/env python3 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/RsaCtfTool/lib/coppersmith.py | 12 | __all__ = [ | CODE |
| LOW | src/RsaCtfTool/lib/number_theory.py | 738 | __all__ = [ | CODE |
| LOW | src/RsaCtfTool/lib/crypto_wrapper.py | 23 | __all__ = ["RSA", "PKCS1_OAEP", "number", "long_to_bytes", "bytes_to_long"] | CODE |
| LOW | src/RsaCtfTool/lib/polynomial.py | 11 | __all__ = ["Polynomial", "PolynomialDivisionError"] | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | src/RsaCtfTool/main.py | 440 | # Check if a private key is provided and there's something to decrypt | STRING |
| LOW⚡ | src/RsaCtfTool/main.py | 447 | # Check if a public key is provided | STRING |
| LOW⚡ | src/RsaCtfTool/main.py | 451 | # Check if n and e are provided | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_audit_regressions.py | 239 | monkeypatch.setenv("WA_API_KEY", "dummy-key") | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_algos.py | 6 | CODE | |
| LOW | tests/test_algos.py | 623 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/RsaCtfTool/lib/keys_wrapper.py | 207 | CODE |