[GH-ISSUE #1772] Cannot get the Root Certificate from Android client X509TrustManager #1765

Closed
opened 2026-03-03 19:54:10 +03:00 by kerem · 22 comments
Owner

Originally created by @4332weizi on GitHub (Sep 18, 2023).
Original GitHub issue: https://github.com/ProxymanApp/Proxyman/issues/1772

Originally assigned to: @NghiaTranUIT on GitHub.

Description

We check the last X509Certificate of the chain, which is passed to the checkServerTrusted function in client X509TrustManager. Then we import our Root Certificate into the proxy, it works fine on Charles but cannot work on Proxyman. When using Proxyman, the size of the chain passed is always 1, and doesn't contain the `Root Certificate

Steps to Reproduce

  1. Check root cert sha256 in X509TrustManager
    private final String CERT_SHA256 = "xxx...xxx"

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        X509Certificate signByRootCert = chain[chain.length - 1];
        MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256");
        String sha256ForCert = toHex(sha256Digest.digest(signByRootCert.getEncoded()));
        if(!TextUtils.equals(CERT_SHA256, sha256ForCert)) {
            throw new CertificateException("xxx")
        }
    }
  1. Import the Root Certificate into Proxyman and Charles
  2. Send a request from Android client
  3. When using Charles:
chain.lenght = 2
TextUtils.equals(CERT_SHA256, sha256ForCert) = true
authType = ECDHE_RSA

When using Proxyman:

chain.lenght = 1
TextUtils.equals(CERT_SHA256, sha256ForCert) = false
authType = GENERIC

Current Behavior

The certificate chain doesn't contain Root Certificate

Expected Behavior

The Root Certificate is the last element of the certificate chain

Environment

  • App version: Proxyman 4.11.0
  • macOS version: macOS Ventura
Originally created by @4332weizi on GitHub (Sep 18, 2023). Original GitHub issue: https://github.com/ProxymanApp/Proxyman/issues/1772 Originally assigned to: @NghiaTranUIT on GitHub. ## Description We check the last `X509Certificate` of the chain, which is passed to the `checkServerTrusted` function in client `X509TrustManager`. Then we import our `Root Certificate` into the proxy, it works fine on Charles but cannot work on Proxyman. When using Proxyman, the size of the `chain` passed is always 1, and doesn't contain the `Root Certificate ## Steps to Reproduce 1. Check root cert sha256 in `X509TrustManager` ``` private final String CERT_SHA256 = "xxx...xxx" @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { X509Certificate signByRootCert = chain[chain.length - 1]; MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256"); String sha256ForCert = toHex(sha256Digest.digest(signByRootCert.getEncoded())); if(!TextUtils.equals(CERT_SHA256, sha256ForCert)) { throw new CertificateException("xxx") } } ``` 2. Import the `Root Certificate` into Proxyman and Charles 3. Send a request from Android client 4. When using Charles: ``` chain.lenght = 2 TextUtils.equals(CERT_SHA256, sha256ForCert) = true authType = ECDHE_RSA ``` When using Proxyman: ``` chain.lenght = 1 TextUtils.equals(CERT_SHA256, sha256ForCert) = false authType = GENERIC ``` ## Current Behavior The certificate chain doesn't contain `Root Certificate` ## Expected Behavior The `Root Certificate` is the last element of the certificate chain ## Environment - App version: Proxyman 4.11.0 - macOS version: macOS Ventura
kerem 2026-03-03 19:54:10 +03:00
Author
Owner

@NghiaTranUIT commented on GitHub (Sep 19, 2023):

Thanks. I will look on it 👍

<!-- gh-comment-id:1724698138 --> @NghiaTranUIT commented on GitHub (Sep 19, 2023): Thanks. I will look on it 👍
Author
Owner

@NghiaTranUIT commented on GitHub (Sep 19, 2023):

Just wondering: If Proxyman Certificate doesn't contain the your custom Root Certificate in a certificate chain, are you able to decrypt HTTPS traffic without SSL errors 🤔 ?

<!-- gh-comment-id:1724698781 --> @NghiaTranUIT commented on GitHub (Sep 19, 2023): Just wondering: If Proxyman Certificate doesn't contain the your custom Root Certificate in a certificate chain, are you able to decrypt HTTPS traffic without SSL errors 🤔 ?
Author
Owner

@4332weizi commented on GitHub (Sep 19, 2023):

I can find the Root Certificate on Chrome Certificate Viewer, I don't know why checkServerTrusted(X509Certificate[] chain, String authType) receives only one X509Certificate.

<!-- gh-comment-id:1724759634 --> @4332weizi commented on GitHub (Sep 19, 2023): I can find the Root Certificate on Chrome Certificate Viewer, I don't know why `checkServerTrusted(X509Certificate[] chain, String authType)` receives only one X509Certificate.
Author
Owner

@NghiaTranUIT commented on GitHub (Sep 19, 2023):

if Proxyman can decrypt HTTPS traffic from your Android, it means the Proxyman Certificate is generated by your custom root certificate -> It also means that it's already in the Certificate Chain.

If it's not true, you get SSL Error on Android devices.

<!-- gh-comment-id:1724766216 --> @NghiaTranUIT commented on GitHub (Sep 19, 2023): if Proxyman can decrypt HTTPS traffic from your Android, it means the Proxyman Certificate is generated by your custom root certificate -> It also means that it's already in the Certificate Chain. If it's not true, you get SSL Error on Android devices.
Author
Owner

@4332weizi commented on GitHub (Sep 19, 2023):

Yes, maybe bugs in my app. I will look into it later.

<!-- gh-comment-id:1724773168 --> @4332weizi commented on GitHub (Sep 19, 2023): Yes, maybe bugs in my app. I will look into it later.
Author
Owner

@4332weizi commented on GitHub (Sep 26, 2023):

Proxyman:
image

Charles:
image

It seems Proxyman does not send the root CA to the certificates list, the server can omit the root CA.

Reference (RFC 5246 - TLS v1.2, sec. 7.4.2. - Server Certificate):

certificate_list
    This is a sequence (chain) of certificates.  The sender's
    certificate MUST come first in the list.  Each following
    certificate MUST directly certify the one preceding it.  Because
    certificate validation requires that root keys be distributed
    independently, the self-signed certificate that specifies the root
    certificate authority MAY be omitted from the chain, under the
    assumption that the remote end must already possess it in order to
    validate it in any case.
<!-- gh-comment-id:1735176292 --> @4332weizi commented on GitHub (Sep 26, 2023): Proxyman: ![image](https://github.com/ProxymanApp/Proxyman/assets/5563945/b0246d32-0a46-4373-944e-f5ed2b23fe06) Charles: ![image](https://github.com/ProxymanApp/Proxyman/assets/5563945/9f870294-06fe-40d4-a4cd-d13015923616) It seems Proxyman does not send the root CA to the certificates list, the server can omit the root CA. Reference ([RFC 5246 - TLS v1.2, sec. 7.4.2. - Server Certificate](https://www.rfc-editor.org/rfc/rfc5246#section-7.4.2)): ``` certificate_list This is a sequence (chain) of certificates. The sender's certificate MUST come first in the list. Each following certificate MUST directly certify the one preceding it. Because certificate validation requires that root keys be distributed independently, the self-signed certificate that specifies the root certificate authority MAY be omitted from the chain, under the assumption that the remote end must already possess it in order to validate it in any case. ```
Author
Owner

@4332weizi commented on GitHub (Sep 27, 2023):

@NghiaTranUIT Can you include an option to send the root CA in the certificate chain?

<!-- gh-comment-id:1736569265 --> @4332weizi commented on GitHub (Sep 27, 2023): @NghiaTranUIT Can you include an option to send the root CA in the certificate chain?
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

please

<!-- gh-comment-id:1767902001 --> @4332weizi commented on GitHub (Oct 18, 2023): please
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

@4332weizi can you use Charles Proxy and print the Root CA ? chain[0] to see the name of the CA Certificate.

I'm not sure how to configure it when using TLSConfiguration.

One of these properties can be fixed:

<!-- gh-comment-id:1767917187 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): @4332weizi can you use Charles Proxy and print the Root CA ? `chain[0]` to see the name of the CA Certificate. I'm not sure how to configure it when using TLSConfiguration. One of these properties can be fixed: - https://github.com/apple/swift-nio-ssl/blob/c05ca760bd3e3a593372e3beec15e3cb60703c35/Sources/NIOSSL/TLSConfiguration.swift#L278 - https://github.com/apple/swift-nio-ssl/blob/c05ca760bd3e3a593372e3beec15e3cb60703c35/Sources/NIOSSL/TLSConfiguration.swift#L325
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

yes, chain[chain.length - 1] is the Root CA
image
image

<!-- gh-comment-id:1767966824 --> @4332weizi commented on GitHub (Oct 18, 2023): yes, `chain[chain.length - 1]` is the Root CA ![image](https://github.com/ProxymanApp/Proxyman/assets/5563945/52e753d5-1a01-4d1b-8c34-49ab8700ef2e) <img width="550" alt="image" src="https://github.com/ProxymanApp/Proxyman/assets/5563945/f4ebbbf9-f2f9-47ee-aeca-50a32d3c85a2">
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

Can you print out the Alternative Subject Name and the Issuer Object?

<!-- gh-comment-id:1767968288 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): Can you print out the Alternative Subject Name and the Issuer Object?
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

chain[0]:

Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Anjuke, OU=Mobile, CN=QA-CN/emailAddress=bianwei02@58ganji.com
X509v3 Subject Alternative Name: DNS:*.fang.anjuke.com, DNS:anjuke.com, DNS:jikejia.cn, DNS:vip.58ganji.com, DNS:cloud-passport.58ganji.com, DNS:*.zu.anjuke.com, DNS:*.xzl.anjuke.com, DNS:*.sp.anjuke.com, DNS:*.news.anjuke.com, DNS:*.haiwai.anjuke.com, DNS:*.brand.anjuke.com, DNS:*.anjuke.com, DNS:*.jikejia.cn, DNS:*.xinfang.anjuke.com, DNS:zu.anjuke.com, DNS:xzl.anjuke.com, DNS:sp.anjuke.com, DNS:news.anjuke.com, DNS:haiwai.anjuke.com, DNS:brand.anjuke.com, DNS:xinfang.anjuke.com, DNS:fang.anjuke.com
<!-- gh-comment-id:1767976640 --> @4332weizi commented on GitHub (Oct 18, 2023): `chain[0]`: ``` Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Anjuke, OU=Mobile, CN=QA-CN/emailAddress=bianwei02@58ganji.com X509v3 Subject Alternative Name: DNS:*.fang.anjuke.com, DNS:anjuke.com, DNS:jikejia.cn, DNS:vip.58ganji.com, DNS:cloud-passport.58ganji.com, DNS:*.zu.anjuke.com, DNS:*.xzl.anjuke.com, DNS:*.sp.anjuke.com, DNS:*.news.anjuke.com, DNS:*.haiwai.anjuke.com, DNS:*.brand.anjuke.com, DNS:*.anjuke.com, DNS:*.jikejia.cn, DNS:*.xinfang.anjuke.com, DNS:zu.anjuke.com, DNS:xzl.anjuke.com, DNS:sp.anjuke.com, DNS:news.anjuke.com, DNS:haiwai.anjuke.com, DNS:brand.anjuke.com, DNS:xinfang.anjuke.com, DNS:fang.anjuke.com ```
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

May I ask: Are you using Custom Certificate ? Or just use as normal (Use Proxyman CA Certificate).

<!-- gh-comment-id:1767981254 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): May I ask: Are you using [Custom Certificate](https://docs.proxyman.io/advanced-features/custom-certificates) ? Or just use as normal (Use Proxyman CA Certificate).
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

I am using a Custom Certificate

<!-- gh-comment-id:1767983861 --> @4332weizi commented on GitHub (Oct 18, 2023): I am using a Custom Certificate
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

Sorry, 1 question: Are you using a Custom Root Certificate, or Server Certificate or Client Certificate ? 🤔

<!-- gh-comment-id:1767989611 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): Sorry, 1 question: Are you using a Custom Root Certificate, or Server Certificate or Client Certificate ? 🤔
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

Custom Root Certificate

image
<!-- gh-comment-id:1767992806 --> @4332weizi commented on GitHub (Oct 18, 2023): Custom Root Certificate <img width="754" alt="image" src="https://github.com/ProxymanApp/Proxyman/assets/5563945/bbd12554-2736-4f2c-98a5-ed7a187aa9cc">
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

Can you try this build: https://download.proxyman.io/beta/Proxyman_4.12.0_Add_to_rootTrusts.dmg

I add the Root Certificate to the trustRoot property. I can't test it because I don't have your setup.

<!-- gh-comment-id:1768058972 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): Can you try this build: https://download.proxyman.io/beta/Proxyman_4.12.0_Add_to_rootTrusts.dmg I add the Root Certificate to the `trustRoot` property. I can't test it because I don't have your setup.
Author
Owner

@4332weizi commented on GitHub (Oct 18, 2023):

seem nothing changed

image

<!-- gh-comment-id:1768066084 --> @4332weizi commented on GitHub (Oct 18, 2023): seem nothing changed ![image](https://github.com/ProxymanApp/Proxyman/assets/5563945/b2b44e4e-9691-43a4-8483-04f60d4d6f04)
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 18, 2023):

How about this build: https://download.proxyman.io/beta/Proxyman_4.12.0_try_to_fix_rootTrusts_v2.dmg

<!-- gh-comment-id:1768244285 --> @NghiaTranUIT commented on GitHub (Oct 18, 2023): How about this build: https://download.proxyman.io/beta/Proxyman_4.12.0_try_to_fix_rootTrusts_v2.dmg
Author
Owner

@4332weizi commented on GitHub (Oct 19, 2023):

Nice, I can see the Root CA now, and SSL Proxying works. Thank you so much!

<!-- gh-comment-id:1769757417 --> @4332weizi commented on GitHub (Oct 19, 2023): Nice, I can see the Root CA now, and SSL Proxying works. Thank you so much!
Author
Owner

@NghiaTranUIT commented on GitHub (Oct 19, 2023):

@4332weizi can you check this build again: https://download.proxyman.io/beta/Proxyman_4.12.0_Fix_Trust_Root_v3.dmg

I did some refactoring and I think it should work as intended. Sorry, I don't have your setup, so I can't verify it by my own.

<!-- gh-comment-id:1769794533 --> @NghiaTranUIT commented on GitHub (Oct 19, 2023): @4332weizi can you check this build again: https://download.proxyman.io/beta/Proxyman_4.12.0_Fix_Trust_Root_v3.dmg I did some refactoring and I think it should work as intended. Sorry, I don't have your setup, so I can't verify it by my own.
Author
Owner

@4332weizi commented on GitHub (Oct 19, 2023):

Just like the previous version!

<!-- gh-comment-id:1769799698 --> @4332weizi commented on GitHub (Oct 19, 2023): Just like the previous version!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Proxyman#1765
No description provided.