Skip to content

ADFA-4633: Remove BouncyCastle#1542

Merged
davidschachterADFA merged 10 commits into
stagefrom
ADFA-4633-remove-bouncycastle-pqc
Jul 18, 2026
Merged

ADFA-4633: Remove BouncyCastle#1542
davidschachterADFA merged 10 commits into
stagefrom
ADFA-4633-remove-bouncycastle-pqc

Conversation

@davidschachterADFA

Copy link
Copy Markdown
Collaborator

Summary

  • Replaces BouncyCastle X.509 certificate generation in ToolsManager.generateKeystore() and AdbKey with a new SelfSignedCert.kt utility that encodes X.509 DER manually using only standard Java SE / Android APIs
  • Removes bcprov-jdk18on and bcpkix-jdk18on runtime dependencies from common and shizuku-manager
  • Removes bcutil-jdk18on from the build-script classpath in settings.gradle.kts
  • Removes the bcprovJdk18on version and both library entries from libs.versions.toml

Test plan

  • Build :common:compileV7DebugKotlin — passes
  • Build :subprojects:shizuku-manager:compileV7DebugKotlin — passes
  • Smoke-test first-launch keystore generation: verify a .p12 file is created at KEYSTORE_RELEASE and keystore.properties is written alongside it
  • Smoke-test ADB wireless pairing: verify the TLS handshake still succeeds

🤖 Generated with Claude Code

…h pure-Java DER encoder

Replaces both usages of BouncyCastle (ToolsManager.generateKeystore and AdbKey certificate
creation) with a minimal self-signed X.509 DER encoder written in standard Java/Kotlin APIs,
eliminating the bcprov-jdk18on and bcpkix-jdk18on runtime dependencies entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Self-signed X.509 certificate creation now uses a shared standard-API DER utility. Keystore and ADB key flows call it, tests cover encoding behavior, and BouncyCastle certificate dependencies and configuration are removed.

Changes

Certificate generation migration

Layer / File(s) Summary
Standard API certificate utility
common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt, common/src/test/java/com/itsaky/androidide/utils/SelfSignedCertTest.kt
Adds DER encoding, RSA signing, distinguished-name handling, validity encoding, X.509 parsing, and tests for verification, locale handling, and escaped commas.
Keystore and ADB key integration
common/src/main/java/com/itsaky/androidide/managers/ToolsManager.java, subprojects/shizuku-manager/src/main/java/moe/shizuku/manager/adb/AdbKey.kt
Routes certificate initialization through SelfSignedCertUtils.generateSelfSignedCert and removes the former BouncyCastle construction path.
Crypto dependency configuration
common/build.gradle.kts, gradle/libs.versions.toml, settings.gradle.kts, subprojects/shizuku-manager/build.gradle.kts
Removes BouncyCastle declarations and adds the updated module dependencies.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ToolsManager
  participant SelfSignedCertUtils
  participant CertificateFactory
  ToolsManager->>SelfSignedCertUtils: Generate certificate from key pair and validity
  SelfSignedCertUtils->>SelfSignedCertUtils: Encode and sign DER certificate
  SelfSignedCertUtils->>CertificateFactory: Parse certificate bytes
  CertificateFactory-->>ToolsManager: Return X509Certificate
Loading

Possibly related PRs

Suggested reviewers: jatezzz, jomen-adfa

Poem

A bunny hops through DER so neat,
With RSA drums beneath its feet.
BouncyCastle leaves the den,
Shared certs bloom for keys again.
Thump, thump! The build runs light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: removing BouncyCastle.
Description check ✅ Passed The description matches the implemented changes and test plan in the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-4633-remove-bouncycastle-pqc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt (2)

14-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace non-ASCII characters with standard ASCII equivalents.

As per coding guidelines: "Use ASCII in code and code comments where an equivalent ASCII character is available; prefer ->, -, and straight quotes over non-ASCII equivalents."

  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L14-L16: Replace the non-ASCII em dash () on line 15 with a standard hyphen (-).
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L109-L112: Replace the non-ASCII em dash () on line 111 with a standard hyphen (-).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt` around
lines 14 - 16, Replace the em dash with an ASCII hyphen in the documentation
comment near SelfSignedCert.kt lines 14-16 and in the comment near lines
109-112; make no other changes.

Source: Coding guidelines


38-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove decorative separator comments.

As per coding guidelines: "Do not add separator or decorative comments such as banner bars, // ==== rules, or ASCII-art dividers."

  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L38-L40: Remove the // ----- separator lines, keeping only the descriptive text // TBSCertificate.
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L60-L63: Remove the // ----- separator lines.
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L91-L93: Remove the // ----- separator lines.
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L100-L102: Remove the // ----- separator lines.
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L136-L138: Remove the // ----- separator lines.
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt#L167-L169: Remove the // ----- separator lines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt` around
lines 38 - 40, Remove the decorative separator lines from all six listed ranges
in common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt: 38-40,
60-63, 91-93, 100-102, 136-138, and 167-169. At the first site, retain only the
descriptive comment “TBSCertificate”; remove the separator lines at the
remaining sites.

Source: Coding guidelines

subprojects/shizuku-manager/src/main/java/moe/shizuku/manager/adb/AdbKey.kt (1)

311-317: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding the L suffix to the large integer literal.

Although Kotlin safely infers 2461449600 as a Long because it exceeds Int.MAX_VALUE, explicitly appending the L suffix (e.g., 2461449600L * 1000) clarifies the intent and removes ambiguity about potential integer overflow for future maintainers.

💡 Proposed optional refactor
 		this.certificate = generateSelfSignedCert(
 			KeyPair(publicKey, privateKey),
 			"CN=00",
 			BigInteger.ONE,
 			Date(0),
-			Date(2461449600 * 1000),
+			Date(2461449600L * 1000),
 		)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@subprojects/shizuku-manager/src/main/java/moe/shizuku/manager/adb/AdbKey.kt`
around lines 311 - 317, Update the expiration-date calculation in the
certificate assignment to mark the large literal as a Long by adding the L
suffix to 2461449600 before multiplying by 1000. Keep the existing
generateSelfSignedCert call and date values unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt`:
- Around line 14-16: Replace the em dash with an ASCII hyphen in the
documentation comment near SelfSignedCert.kt lines 14-16 and in the comment near
lines 109-112; make no other changes.
- Around line 38-40: Remove the decorative separator lines from all six listed
ranges in common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt:
38-40, 60-63, 91-93, 100-102, 136-138, and 167-169. At the first site, retain
only the descriptive comment “TBSCertificate”; remove the separator lines at the
remaining sites.

In `@subprojects/shizuku-manager/src/main/java/moe/shizuku/manager/adb/AdbKey.kt`:
- Around line 311-317: Update the expiration-date calculation in the certificate
assignment to mark the large literal as a Long by adding the L suffix to
2461449600 before multiplying by 1000. Keep the existing generateSelfSignedCert
call and date values unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7d0deae-2b7f-4afc-82d7-0f0874077620

📥 Commits

Reviewing files that changed from the base of the PR and between 51b1605 and cceaa91.

📒 Files selected for processing (7)
  • common/build.gradle.kts
  • common/src/main/java/com/itsaky/androidide/managers/ToolsManager.java
  • common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt
  • gradle/libs.versions.toml
  • settings.gradle.kts
  • subprojects/shizuku-manager/build.gradle.kts
  • subprojects/shizuku-manager/src/main/java/moe/shizuku/manager/adb/AdbKey.kt
💤 Files with no reviewable changes (4)
  • common/build.gradle.kts
  • settings.gradle.kts
  • gradle/libs.versions.toml
  • subprojects/shizuku-manager/build.gradle.kts

@davidschachterADFA

Copy link
Copy Markdown
Collaborator Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, comment @claude review on this pull request to trigger a review.

davidschachterADFA and others added 4 commits July 17, 2026 09:59
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace em dashes with ASCII hyphens in two comments
- Remove decorative separator lines from section headers
- Add L suffix to long literal in AdbKey to prevent integer overflow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@hal-eisen-adfa hal-eisen-adfa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review (xhigh) of the hand-rolled DER certificate encoder that replaces BouncyCastle. The ASN.1 structure is byte-correct (independently verified against RFC 5280 and strict parsers), but there are two runtime-breaking bugs plus lower-severity issues. Inline comments below. The BouncyCastle removal itself is clean: the settings.gradle bcutil classpath and the Security/BouncyCastleProvider imports were effectively dead, nothing else in the app uses the BC provider, and keystore-generator-plugin keeps its own BC dep and is unaffected.

Note: this new security-critical encoder ships with no unit tests. Worth a round-trip test (generate -> CertificateFactory parse -> assert DN/validity/signature) plus a Locale.setDefault(Locale("ar")) regression test that would have caught finding #2.

Comment thread common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt Outdated
Comment thread common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt Outdated
Comment thread common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt Outdated
Comment thread common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt Outdated
Comment thread common/src/main/java/com/itsaky/androidide/utils/SelfSignedCert.kt Outdated
davidschachterADFA and others added 2 commits July 17, 2026 15:45
- BigInteger.TWO is API 33+ (NoSuchFieldError on Android 9-12); replace
  with BigInteger.valueOf(2) (as AdbKey.kt already did).
- String.format with default locale corrupts UTCTime/GeneralizedTime bytes
  on Arabic/Persian/Bengali locales; pass Locale.ROOT explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Encode countryName as PrintableString (tag 0x13) instead of UTF8String,
  per RFC 5280 App. A.
- Generalize tlv() long-form length encoding to support content >= 64KiB
  (was hardcoded to 2 length octets, silently truncating longer content).
- Split DN parts on unescaped commas only (RFC 4514-style backslash
  escaping), so values like "O=Foo\, Inc." don't get split into two RDNs.
- Add round-trip unit tests: signature verification, a non-default-locale
  regression test, and an escaped-comma DN test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidschachterADFA

Copy link
Copy Markdown
Collaborator Author

Addressed the remaining review feedback on SelfSignedCert.kt in 005b50e:

  • countryName conformance — now encoded as PrintableString (tag 0x13) instead of UTF8String, per RFC 5280 App. A.
  • tlv() length-encoding truncation — the long-form length was hardcoded to 2 octets, silently truncating content >= 64KiB. Generalized to a variable-length encoding so it's correct at any size (not reachable today at RSA-2048, but no longer a landmine if key size grows).
  • DN parsing on unescaped commasencodeDn now splits on commas per RFC 4514 (a backslash escapes the following character), so a value like O=Foo\, Inc. no longer gets split into two RDNs.
  • Test coverage — added SelfSignedCertTest.kt: a signature round-trip/verify test, a non-default-locale regression test (ar) that would have caught the earlier locale bug, and an escaped-comma DN test.

The two runtime-breaking bugs (BigInteger.TWO NoSuchFieldError on API 28-32, and locale-corrupted cert timestamps) were already fixed in dc63743. common and shizuku-manager both compile clean and all new tests pass.

Fixes found by an xhigh code-review pass (4 independent finder angles
converged on the Calendar bug):

- derTime called Calendar.getInstance(TimeZone) without a Locale, so on
  a device whose default locale uses a non-Gregorian calendar (e.g. Thai
  th-TH) it silently returned a BuddhistCalendar with YEAR = Gregorian +
  543, corrupting cert validity dates for both the release keystore and
  ADB pairing. Pass Locale.ROOT explicitly.
- derTime now also emits GeneralizedTime for years < 1950 (previously
  only checked the upper 2050 bound), matching BouncyCastle's Time class,
  and the UTCTime string is now derived from the GeneralizedTime one
  instead of duplicating the format/cal.get() calls.
- derPrintableString validated nothing and encoded with plain US_ASCII,
  which silently replaces any non-ASCII character with '?' instead of
  failing; it now validates against PrintableString's legal charset.
- encodeDn silently dropped empty-valued RDNs and unrecognized attribute
  keys, diverging from BouncyCastle's X500Name (which kept empty RDNs
  and threw on genuinely unrecognized ones). It now preserves empty
  values and throws IllegalArgumentException for malformed components
  or unsupported attribute types instead of silently dropping them.
- Removed four one-line decorative section comments per CLAUDE.md's
  no-separator-comments rule.

Test suite: the existing locale-regression test used "ar", which never
changes the JVM's Calendar implementation and so never exercised the bug
above; switched it to "th"-TH and added assertions on the decoded
notBefore/notAfter (the prior test only checked cert.verify(), which
validates the signature but not the date values, so it couldn't have
caught this class of bug even with the right locale). Added coverage for
the pre-1950 boundary, preserved empty DN values, and the three new
IllegalArgumentException cases.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidschachterADFA

Copy link
Copy Markdown
Collaborator Author

Ran an xhigh-effort multi-angle review of this PR and fixed everything it surfaced (8c4f986):

  • Calendar locale bug (the big one)derTime called Calendar.getInstance(TimeZone) without a Locale, so on a device whose default locale uses a non-Gregorian calendar (e.g. Thai th-TH) it silently returned a BuddhistCalendar whose YEAR field is Gregorian + 543. That corrupted year got baked into the cert's notBefore/notAfter, breaking both release-keystore signing and ADB wireless pairing on those locales. Fixed by passing Locale.ROOT explicitly. Four independent review angles converged on this one; confirmed by reproduction (Thai locale -> year 2513 for epoch instead of 1970), and confirmed the fix by temporarily reverting it and watching the new regression test fail.
  • derTime lower bound — now also emits GeneralizedTime for years < 1950 (previously only checked the upper 2050 bound), matching BouncyCastle's Time class. Also deduplicated the UTCTime/GeneralizedTime branches.
  • derPrintableString — validated nothing and encoded with plain US_ASCII, which silently replaces non-ASCII with ? instead of failing. Now validates against PrintableString's legal charset and throws.
  • encodeDn — silently dropped empty-valued RDNs and unrecognized attribute keys, diverging from BouncyCastle's X500Name (which kept empty RDNs and threw on truly unrecognized ones). Now preserves empty values and throws IllegalArgumentException for malformed components or unsupported attribute types.
  • Decorative comments — removed 4 one-line section-label comments per this repo's no-separator-comments convention.
  • Test suite — the existing locale-regression test used "ar", which never changes the JVM's Calendar implementation and so never exercised the bug above; switched to "th"-TH and added assertions on the decoded notBefore/notAfter (the old test only checked cert.verify(), which validates the signature but not the date values — it couldn't have caught this class of bug even with the right locale). Added coverage for the pre-1950 boundary, preserved empty DN values, and the three new IllegalArgumentException cases. 8/8 tests pass; both call sites (ToolsManager, AdbKey) compile clean.

Deliberately left alone (suggestion-level findings, not confirmed bugs): swapping the hand-rolled DN encoder for javax.security.auth.x500.X500Principal (bigger redesign, real Android-compatibility risk, needs on-device verification), and keystore-generator-plugin's continued BouncyCastle dependency (separate module with its own DN needs, out of scope here).

@davidschachterADFA
davidschachterADFA merged commit 1d161d7 into stage Jul 18, 2026
4 checks passed
@davidschachterADFA
davidschachterADFA deleted the ADFA-4633-remove-bouncycastle-pqc branch July 18, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants