gpt4 book ai didi

android - 使用 Retrofit Android 的相互身份验证

转载 作者:行者123 更新时间:2023-12-03 17:12:46 28 4
gpt4 key购买 nike

我需要在 api 请求中发送 .CRT 和 .KEY 文件。我设法使用 Postman 完成了请求,但我不知道如何在 android 代码中传递 key 。
enter image description here

阴极射线管:

-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

key :
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

这是我的客户
fun getClient(url: String, context: Context): Retrofit {

// Loading CAs from an InputStream
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")

val ca: Certificate = context.resources.openRawResource(R.raw.crt).use { cert -> cf.generateCertificate(cert) }

// Creating a KeyStore containing our trusted CAs
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType).apply {
load(null, null)
setCertificateEntry("ca", ca)
}

// Creating a TrustManager that trusts the CAs in our KeyStore.
val tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm()
val tmf = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
init(keyStore)
}

val trustManager: X509TrustManager = tmf.trustManagers[0] as X509TrustManager

// Creating an SSLSocketFactory that uses our TrustManager
val sslContext = SSLContext.getInstance("TLS").apply {
init(null, arrayOf<TrustManager>(trustManager), null)
}

val okHttpClient = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustManager)
.build()

val json = GsonBuilder().setLenient().create()

return Retrofit
.Builder()
.baseUrl(url)
.client(okHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(json))
.build()
}

该调用返回一个 throwable:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.



我很感激谁能帮助我。对不起,我的英语不好。

最佳答案

看起来您的 Retrofit ssl 配置与您配置 postman 的方式不匹配。在 postman 中,您已将其配置为在客户端证书配置部分中具有私钥和证书链。受信任的证书/CA 为空。现在,如果我们将其与您的 retrofit 配置进行比较,我可以看到您添加了 certificate.crt文件作为受信任的证书而不是客户端 key Material 。
由于我们没有证书,因此很难复制完全相同的情况,所以我从 https://badssl.com/ 中获取一个。我们可以用它来轻松地测试这个用例。
我在这里添加证书,但您可能需要从网站本身获取一个新证书,因为它们将过期。
这个用例基本上需要 3 个文件:

  • 客户端私钥
  • 客户端证书链
  • 受信任的服务器证书

  • 1.客户端私钥
    -----BEGIN PRIVATE KEY-----
    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHN18R6x5Oz+u6
    SOXLoxIscz5GHR6cDcCLgyPax2XfXHdJs+h6fTy61WGM+aXEhR2SIwbj5997s34m
    0MsbvkJrFmn0LHK1fuTLCihEEmxGdCGZA9xrwxFYAkEjP7D8v7cAWRMipYF/JP7V
    U7xNUo+QSkZ0sOi9k6bNkABKL3+yP6PqAzsBoKIN5lN/YRLrppsDmk6nrRDo4R3C
    D+8JQl9quEoOmL22Pc/qpOjL1jgOIFSE5y3gwbzDlfCYoAL5V+by1vu0yJShTTK8
    oo5wvphcFfEHaQ9w5jFg2htdq99UER3BKuNDuL+zejqGQZCWb0Xsk8S5WBuX8l3B
    rrg5giqNAgMBAAECggEAVRB/t9b9igmeTlzyQpHPIMvUu3uTpm742JmWpcSe61FA
    XmhDzInNdLnIfbnb3p44kj4Coy5PbzKlm01sbNxA4BkiBPE1yen1J/2eU/LJ6QuN
    jRjo9drFfR75UWPQ3xu9uJhQY2rocLILXmvy69FlG+ebThh8SPbTMtNaTFMb47An
    pk2FrW9+rzPswbklOxls/SDt78usRvfAjslm73IdBTOrbceF+GmYs3/SXz1gu05p
    LxY2rhC8piBlqnD/QbXBahZbhjb9SkDFn2typMFZKkJIIKDJaOI2E9tIlZ97/0nZ
    txqchMty8IuU9YYAfLXCmj2IEfnvLtL7thLfKLuWAQKBgQDyXBpEgKFzfy2a1AI0
    +1qL/u5UN14l7S6/wmyDTgVMXwoxhwPRXWD5PutQ8D6tMfC/y4AYt3OXg1blCvLD
    XysNj5SK+dpmQR0SyeWjd9zwxJAXvx0McJefCYd86YGcGhJsuX5bkHIeQlEc6df7
    yoqr1480VQx/+Fk1i6Zr0EIUFQKBgQDSbalUOfXZh2EVRQEgf3VoPlxAiwGGQcVT
    i+pbjMG3pOwmkVyJZusGtN5HN4Oi7n1oiyfMYGsszKQ5j4TDBGS70pNUzhTv3Vn8
    0Vsfz0arJRqJxviiv4FfDmsYXwObNKwOjR+LEn1NUPkOYOLdz1lDuWOu11LE90Dy
    Q6hg8WwCmQKBgQDTy5lI9AAjpqh7/XpQQrhGT2qHPjuQeU25Vnbt6GjI7OVDkvHL
    LQdpyYprGQgs4s+5TGWNNARYC/cMAh1Ujv5Yw3jUWrR5V73IhZeg20bBQYWKuwDv
    thVKblFw377cZAxl51R9QCX6O4oW8mRFLiMxORd0bD6YNrf/CyNMZJraYQKBgAE7
    o0JbFJWxtV/qh5cpKAb0VpYKOngO6pkSuMzQhlINJVUUhPZJJBdl9+dy69KIkzOJ
    nTIVXotkp5GuxZhe7jgrg7F7g6PkKCLTFzWYgVF/ZihoggxyEs/7xaTe6aZ/KILt
    UMH/2bwaPVtYNfwWuu8qpurfWBzPVhIVU2c+AuQBAoGAXMbw10vyiznlhyMFw5kx
    SzlBMqJBLJkzQBtpvXuT0lqqxTSNC3N4WxgVOLCHa6HqXiB0790YL8/RWunsXTk2
    c7ugThP6iMPNVAycWkIF4vvHTwZ9RCSmEQabRaqGGLz/bhLL3fi3lPGCR+iW2Dxq
    GTH3fhaM/pZZGdIC75x/69Y=
    -----END PRIVATE KEY-----
    2.客户端证书链
    -----BEGIN CERTIFICATE-----
    MIIEqDCCApCgAwIBAgIUK5Ns4y2CzosB/ZoFlaxjZqoBTIIwDQYJKoZIhvcNAQEL
    BQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
    DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDExMC8GA1UEAwwoQmFkU1NM
    IENsaWVudCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xOTExMjcwMDE5
    NTdaFw0yMTExMjYwMDE5NTdaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
    Zm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wx
    IjAgBgNVBAMMGUJhZFNTTCBDbGllbnQgQ2VydGlmaWNhdGUwggEiMA0GCSqGSIb3
    DQEBAQUAA4IBDwAwggEKAoIBAQDHN18R6x5Oz+u6SOXLoxIscz5GHR6cDcCLgyPa
    x2XfXHdJs+h6fTy61WGM+aXEhR2SIwbj5997s34m0MsbvkJrFmn0LHK1fuTLCihE
    EmxGdCGZA9xrwxFYAkEjP7D8v7cAWRMipYF/JP7VU7xNUo+QSkZ0sOi9k6bNkABK
    L3+yP6PqAzsBoKIN5lN/YRLrppsDmk6nrRDo4R3CD+8JQl9quEoOmL22Pc/qpOjL
    1jgOIFSE5y3gwbzDlfCYoAL5V+by1vu0yJShTTK8oo5wvphcFfEHaQ9w5jFg2htd
    q99UER3BKuNDuL+zejqGQZCWb0Xsk8S5WBuX8l3Brrg5giqNAgMBAAGjLTArMAkG
    A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgeAMAsGA1UdDwQEAwIF4DANBgkqhkiG
    9w0BAQsFAAOCAgEAZBauLzFSOijkDadcippr9C6laHebb0oRS54xAV70E9k5GxfR
    /E2EMuQ8X+miRUMXxKquffcDsSxzo2ac0flw94hDx3B6vJIYvsQx9Lzo95Im0DdT
    DkHFXhTlv2kjQwFVnEsWYwyGpHMTjanvNkO7sBP9p1bN1qTE3QAeyMZNKWJk5xPl
    U298ERar6tl3Z2Cl8mO6yLhrq4ba6iPGw08SENxzuAJW+n8r0rq7EU+bMg5spgT1
    CxExzG8Bb0f98ZXMklpYFogkcuH4OUOFyRodotrotm3iRbuvZNk0Zz7N5n1oLTPl
    bGPMwBcqaGXvK62NlaRkwjnbkPM4MYvREM0bbAgZD2GHyANBTso8bdWvhLvmoSjs
    FSqJUJp17AZ0x/ELWZd69v2zKW9UdPmw0evyVR19elh/7dmtF6wbewc4N4jxQnTq
    IItuhIWKWB9edgJz65uZ9ubQWjXoa+9CuWcV/1KxuKCbLHdZXiboLrKm4S1WmMYW
    d0sJm95H9mJzcLyhLF7iX2kK6K9ug1y02YCVXBC9WGZc2x6GMS7lDkXSkJFy3EWh
    CmfxkmFGwOgwKt3Jd1pF9ftcSEMhu4WcMgxi9vZr9OdkJLxmk033sVKI/hnkPaHw
    g0Y2YBH5v0xmi8sYU7weOcwynkjZARpUltBUQ0pWCF5uJsEB8uE8PPDD3c4=
    -----END CERTIFICATE-----
    3.可信服务器证书
    -----BEGIN CERTIFICATE-----
    MIIGqDCCBZCgAwIBAgIQCvBs2jemC2QTQvCh6x1Z/TANBgkqhkiG9w0BAQsFADBN
    MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
    aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMjAwMzIzMDAwMDAwWhcN
    MjIwNTE3MTIwMDAwWjBuMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5p
    YTEVMBMGA1UEBxMMV2FsbnV0IENyZWVrMRwwGgYDVQQKExNMdWNhcyBHYXJyb24g
    VG9ycmVzMRUwEwYDVQQDDAwqLmJhZHNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUA
    A4IBDwAwggEKAoIBAQDCBOz4jO4EwrPYUNVwWMyTGOtcqGhJsCK1+ZWesSssdj5s
    wEtgTEzqsrTAD4C2sPlyyYYC+VxBXRMrf3HES7zplC5QN6ZnHGGM9kFCxUbTFocn
    n3TrCp0RUiYhc2yETHlV5NFr6AY9SBVSrbMo26r/bv9glUp3aznxJNExtt1NwMT8
    U7ltQq21fP6u9RXSM0jnInHHwhR6bCjqN0rf6my1crR+WqIW3GmxV0TbChKr3sMP
    R3RcQSLhmvkbk+atIgYpLrG6SRwMJ56j+4v3QHIArJII2YxXhFOBBcvm/mtUmEAn
    hccQu3Nw72kYQQdFVXz5ZD89LMOpfOuTGkyG0cqFAgMBAAGjggNhMIIDXTAfBgNV
    HSMEGDAWgBQPgGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUne7Be4ELOkdp
    cRh9ETeTvKUbP/swIwYDVR0RBBwwGoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29t
    MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
    awYDVR0fBGQwYjAvoC2gK4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Et
    c2hhMi1nNi5jcmwwL6AtoCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2Nh
    LXNoYTItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUH
    AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIDMHwGCCsG
    AQUFBwEBBHAwbjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
    MEYGCCsGAQUFBzAChjpodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
    cnRTSEEyU2VjdXJlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwggF+BgorBgEE
    AdZ5AgQCBIIBbgSCAWoBaAB2ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaO
    HtGFAAABcQhGXioAAAQDAEcwRQIgDfWVBXEuUZC2YP4Si3AQDidHC4U9e5XTGyG7
    SFNDlRkCIQCzikrA1nf7boAdhvaGu2Vkct3VaI+0y8p3gmonU5d9DwB2ACJFRQdZ
    VSRWlj+hL/H3bYbgIyZjrcBLf13Gg1xu4g8CAAABcQhGXlsAAAQDAEcwRQIhAMWi
    Vsi2vYdxRCRsu/DMmCyhY0iJPKHE2c6ejPycIbgqAiAs3kSSS0NiUFiHBw7QaQ/s
    GO+/lNYvjExlzVUWJbgNLwB2AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7U
    iwXlAAABcQhGXnoAAAQDAEcwRQIgKsntiBqt8Au8DAABFkxISELhP3U/wb5lb76p
    vfenWL0CIQDr2kLhCWP/QUNxXqGmvr1GaG9EuokTOLEnGPhGv1cMkDANBgkqhkiG
    9w0BAQsFAAOCAQEA0RGxlwy3Tl0lhrUAn2mIi8LcZ9nBUyfAcCXCtYyCdEbjIP64
    xgX6pzTt0WJoxzlT+MiK6fc0hECZXqpkTNVTARYtGkJoljlTK2vAdHZ0SOpm9OT4
    RLfjGnImY0hiFbZ/LtsvS2Zg7cVJecqnrZe/za/nbDdljnnrll7C8O5naQuKr4te
    uice3e8a4TtviFwS/wdDnJ3RrE83b1IljILbU5SV0X1NajyYkUWS7AnOmrFUUByz
    MwdGrM6kt0lfJy/gvGVsgIKZocHdedPeECqAtq7FAJYanOsjNN9RbBOGhbwq0/FP
    CC01zojqS10nGowxzOiqyB4m6wytmzf0QwjpMw==
    -----END CERTIFICATE-----
    有多种方法可以将这些文件加载​​到您的应用程序中并将它们转换为正确的 ssl Material 。如果您的 pem 文件(私钥)具有不同的 header ,则使用 vanilla java 您可能需要对其进行调整。但是对于上面的例子,下面的代码 fragment 应该可以工作:
    选项 1
    import javax.net.ssl.KeyManager;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    import java.io.IOException;
    import java.io.InputStream;
    import java.nio.charset.Charset;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.security.KeyFactory;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.util.Base64;

    public class App {

    public static void main(String[] args) throws Exception {
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

    InputStream trustedCertificateAsInputStream = Files.newInputStream(Paths.get("badssl-server-certificate.pem"), StandardOpenOption.READ);
    Certificate trustedCertificate = certificateFactory.generateCertificate(trustedCertificateAsInputStream);
    KeyStore trustStore = createEmptyKeyStore("secret".toCharArray());
    trustStore.setCertificateEntry("badssl-server", trustedCertificate);

    String privateKeyContent = new String(Files.readAllBytes(Paths.get("private-key-badssl.pem")), Charset.defaultCharset())
    .replace("-----BEGIN PRIVATE KEY-----", "")
    .replaceAll(System.lineSeparator(), "")
    .replace("-----END PRIVATE KEY-----", "");

    byte[] privateKeyAsBytes = Base64.getDecoder().decode(privateKeyContent);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyAsBytes);

    InputStream certificateChainAsInputStream = Files.newInputStream(Paths.get("certificate-chain-badssl.pem"), StandardOpenOption.READ);
    Certificate certificateChain = certificateFactory.generateCertificate(certificateChainAsInputStream);

    KeyStore identityStore = createEmptyKeyStore("secret".toCharArray());
    identityStore.setKeyEntry("client", keyFactory.generatePrivate(keySpec), "".toCharArray(), new Certificate[]{certificateChain});

    trustedCertificateAsInputStream.close();
    certificateChainAsInputStream.close();

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(trustStore);
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(identityStore, "secret".toCharArray());
    KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, trustManagers, null);

    SSLSocketFactory socketFactory = sslContext.getSocketFactory();


    val okHttpClient = OkHttpClient.Builder()
    .sslSocketFactory(socketFactory, trustManagers[0])
    .build()

    val json = GsonBuilder().setLenient().create()

    val retrofit = Retrofit.Builder()
    .baseUrl("https://client.badssl.com/")
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create(json))
    .build()
    }

    public static KeyStore createEmptyKeyStore(char[] keyStorePassword) throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, keyStorePassword);
    return keyStore;
    }

    }
    这有点冗长,但这应该可以解决问题。我已经用 vanilla java 编写了这个,但是您的 IDEA 应该能够轻松地将其转换为 kotlin。
    上述设置还有一个替代方案,我在自己的库中提供了它,请参见此处: GitHub - SSLContext Kickstart请参阅下面的选项 2 下的示例用法。
    选项 2
    X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial("certificate-chain-badssl.pem", "private-key-badssl.pem");
    X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial("badssl-server-certificate.pem");

    SSLFactory sslFactory = SSLFactory.builder()
    .withIdentityMaterial(keyManager)
    .withTrustMaterial(trustManager)
    .build();

    val okHttpClient = OkHttpClient.Builder()
    .sslSocketFactory(sslFactory.getSslSocketFactory(), sslFactory.getTrustManager().get())
    .build()

    val json = GsonBuilder().setLenient().create()

    val retrofit = Retrofit.Builder()
    .baseUrl("https://client.badssl.com/")
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create(json))
    .build()

    关于android - 使用 Retrofit Android 的相互身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59000913/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com