JAVA简单实现国密双向认证

要实现国密双向认证的数据发送,需要使用支持国密算法的Java库,并且确保HTTP客户端能够处理SSL/TLS连接时的客户端证书验证。

在这个例子中,使用Java标准库结合Bouncy Castle作为提供国密算法的支持。

下面是一个简化的示例,展示如何使用Java实现国密双向认证的数据发送。

请注意,实际开发中可能需要更多的错误处理和配置细节。

首先,确保你已经添加了Bouncy Castle作为安全提供者,以支持国密算法:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;

public class GmProviderInitializer {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
}

 接下来,我们需要一个GmHttpClient类来处理HTTP请求。这个类将使用Apache HttpClient来发送请求,并使用Bouncy Castle来处理SSL连接。

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfoBuilder;
import org.bouncycastle.pkcs.PKCS8PrivateKeyInfo;
import org.bouncycastle.pkcs.PKCS8PrivateKeyInfoBuilder;
import org.bouncycastle.pkcs.PKCSException;
import org.bouncycastle.pkcs.PKCSPrivateKey;
import org.bouncycastle.x509.X509CertificateHolder;
import org.bouncycastle.x509.X509v3CertificateBuilder;
import org.bouncycastle.x509.extension.X509Extensions;
import org.bouncycastle.x509.util.X509Principal;
import org.bouncycastle.x509.util.X509TBSCertificateBuilder;
import org.bouncycastle.x509.util.X509Time;
import org.bouncycastle.x509.util.X509v3TBSCertificateBuilder;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class GmHttpClient {

    private KeyStore encCertStore;
    private KeyStore sigCertStore;

    public void setEncCert(String path) throws Exception {
        loadKeyStore(path, "encCertStore");
    }

    public void setSigCert(String path) throws Exception {
        loadKeyStore(path, "sigCertStore");
    }

    private void loadKeyStore(String path, String storeName) throws Exception {
        try (InputStream is = this.getClass().getResourceAsStream(path)) {
            if (is == null) {
                throw new FileNotFoundException("Resource not found: " + path);
            }
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(is, "password".toCharArray()); // Change password as needed.
            if ("encCertStore".equals(storeName)) {
                encCertStore = ks;
            } else {
                sigCertStore = ks;
            }
        }
    }

    public static String sendPost(String url, Map<String, String> params) throws Exception {
        SSLContext sslContext = createSslContext();

        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build()) {

            HttpPost httpPost = new HttpPost(url);

            httpPost.setHeader("Content-Type", "application/json");
            StringEntity entity = new StringEntity(objectToJson(params), StandardCharsets.UTF_8);
            httpPost.setEntity(entity);

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        }
    }

    private static SSLContext createSslContext() throws Exception {
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        try (InputStream is = GmHttpClient.class.getResourceAsStream("/cert/VHD_ENC.p12")) {
            keyStore.load(is, "password".toCharArray());
        }
        keyManagerFactory.init(keyStore, "password".toCharArray());

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

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom());
        return sslContext;
    }

    private static String objectToJson(Map<String, String> obj) {
        StringBuilder json = new StringBuilder();
        json.append("{");
        for (Map.Entry<String, String> entry : obj.entrySet()) {
            json.append("\"").append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\",");
        }
        if (json.length() > 1) {
            json.setLength(json.length() - 1); // Remove last comma
        }
        json.append("}");
        return json.toString();
    }
}

然后,使用这个类来发送一个POST请求:

public class Main {
    public static void main(String[] args) throws Exception {
        GmHttpClient client = new GmHttpClient();
        client.setEncCert("classpath:cert/VHD_ENC.p12");
        client.setSigCert("classpath:cert/VHD_SIG.p12");

        HashMap<String, String> params = new HashMap<>();
        params.put("param", "请求参数值");

        String url = "https://192.168.2.100:1443/client/v1/list";
        String result = GmHttpClient.sendPost(url, params);
        System.out.println(result);
    }
}

这个示例中的createSslContext方法假设客户端证书是在运行时从资源路径读取的,你需要确保这些证书文件存在于指定的路径中,并且具有正确的密码。此外,这里简化了一些细节,例如证书的验证过程和异常处理等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shootero@126.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值