gin使用自签名SSL证书与自签名证书不受信任方法解决

news2024/12/23 15:02:35

文章目录

    • 1. X.509 V3证书介绍
    • 2、使用openssl生成自签名证书和解决不受信任问题
      • 2.1、生成根证书
      • 2.2、为域名生成证书申请文件
      • 2.3、为域名创建证书的扩展描述文件
      • 2.4、为域名创建证书
    • 3、Go应用中使用自签名证书
      • 3.1、gin框架调用实现
      • 3.2、运行效果
    • 4、使用java的bouncycastle生成ssl证书

1. X.509 V3证书介绍

X.509 是公钥证书的格式标准, 广泛用于 TLS/SSL 安全通信或者其他需要认证的环境中。
X.509 证书可以由 CA(Certificate Authority,数字证书认证机构)颁发,也可以自签名产生。

*X.509 证书中主要含有公钥、身份信息、签名信息和有效性信息等信息,这些信息用于构建一个验证公钥的体系。

- 公钥 : 非对称密码中的公钥。公钥证书的目的就是为了在互联网上分发公钥。
- 身份信息 : 公钥对应的私钥持有者的信息,域名以及用途等。
- 签名信息 : 对公钥进行签名的信息,提供公钥的验证链。可以是 CA
- 的签名或者是自签名,不同之处在于CA证书的根证书大都内置于操作系统或者浏览器中,而自签名证书的公钥验证链则需要自己维护(手动导入到操作系统中或者再验证流程中单独提供自签名的根证书)。
- 有效性信息:证书的有效时间区间,以及 CRL(证书吊销列表)等相关信息。
- X.509 证书的标准规范RFC5280中详细描述了证书的 Encoding Format(编码格式)和Structure(证书结构)。

X.509 证书相关文件常见的扩展名

  • .pem : 隐私增强型电子邮件格式(缩写:PEM)格式,通常是由证书的 DER 二进制 Base64 编码得出。(最常用)。
  • .key : PEM 格式的私钥文件。
  • .pub : PEM 格式的公钥文件。
  • .crt : PEM 格式的公钥证书文件,也可能是 DER。
  • .cer : DER 格式的公钥证书文件,也可能是 PEM。
  • .crs : PEM 格式的 CSR 文件,也可能是 DER。
  • .p12 – PKCS#12 格式,包含证书的同时可能还包含私钥。
  • .pfx – PFX,PKCS#12 之前的格式(通常用PKCS#12格式,比如由互联网信息服务产生的 PFX 文件)。

2、使用openssl生成自签名证书和解决不受信任问题

openssl命令行工具用于从shell程序使用OpenSSL加密库的各种加密功能。 它可以用于:

创建和管理私钥,公钥和参数
公钥加密操作
创建X.509证书,CSR和CRL
消息摘要的计算
使用密码进行加密和解密
SSL / TLS客户端和服务器测试
处理S / MIME签名或加密的邮件
时间戳记请求,生成和验证

2.1、生成根证书

# 生成根证书CA.crt和根证书私钥CA.key
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -subj "/C=CN/ST=GD/L=GD/O=PenngoDev/CN=Create by penngo" -keyout CA.key -out CA.crt -reqexts v3_req -extensions v3_ca

2.2、为域名生成证书申请文件

# 创建证书的私钥
openssl genrsa -out penngo.test.key 2048
# 根据私钥创建一个证书申请文件private.csr,注意证书主体的描述使用-subj参数描述,CN必须和应用中请求的地址一致,可以是IP地址或域名
openssl req -new -key penngo.test.key -subj "/C=CN/ST=GD/L=GD/O=penngo_test/CN=www.penngo.test" -sha256 -out penngo.test.csr

2.3、为域名创建证书的扩展描述文件

根据证书申请文件创建证书的扩展描述文件,如果不使用扩展描述文件,那么在浏览器中无法授信,会提示证书无效。

#penngo.test.ext
[ req ]
default_bits        = 1024
distinguished_name  = req_distinguished_name
req_extensions      = ptest
extensions          = ptest
[ req_distinguished_name ]
countryName         = CN
stateOrProvinceName = Definesys
localityName        = Definesys
organizationName    = Definesys
[PTEST]
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = DNS:www.penngo.test

2.4、为域名创建证书

根据penngo.test.csr文件和penngo.test.ext、以及根证书CA.crt创建一个域名证书penngo.test.crt

openssl x509 -req -days 365 -in penngo.test.csr -CA CA.crt -CAkey CA.key -CAcreateserial -sha256 -out penngo.test.crt -extfile penngo.test.ext -extensions PTEST

最终生成的文件包括:

CA.crt  # 根证书
CA.key  # 根证书私钥
penngo.test.crt # 域名证书
penngo.test.key # 域名证书私钥

根证书中的主体描述可以随意填,但是域名证书中的主体的CN必须和请求地址中的IP或域名一致。

双击根证书CA.crt选择安装证书,注意在选择安装区域时,一定要选择“受信任的根证书颁发机构”。

3、Go应用中使用自签名证书

3.1、gin框架调用实现

package main
import (
	"github.com/gin-gonic/gin"
	"html/template"
)
var html = template.Must(template.New("https").Parse(`
<html>
<head>
  <title>Https Test</title>
  <script src="/assets/app.js"></script>
</head>
<body>
  <h1>Welcome, Test!</h1>
</body>
</html>
`))
func main() {
	r := gin.Default()
	r.Static("/assets", "./assets")
	r.SetHTMLTemplate(html)

	r.GET("/", func(c *gin.Context) {
		c.HTML(200, "https", gin.H{
			"status": "success",
		})
	})

	// 监听并在 https://127.0.0.1:8080 上启动服务
	r.RunTLS(":443", "./testdata/penngo.test.crt", "./testdata/penngo.test.key")
}

3.2、运行效果

在这里插入图片描述

4、使用java的bouncycastle生成ssl证书

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.penngo</groupId>
        <artifactId>code_test</artifactId>
        <version>1.0</version>
    </parent>

    <artifactId>tls_https</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk18on -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-ext-jdk18on</artifactId>
            <version>1.77</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk18on -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk18on</artifactId>
            <version>1.77</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.15.1</version>
        </dependency>
    </dependencies>
</project>

X509V3CreateExample.java

package com.penngo;

import java.io.File;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;

/**
 * Basic X.509 V3 Certificate creation with TLS flagging.
 */
public class X509V3CreateExample {
    static {
        try {
            Security.addProvider(new BouncyCastleProvider());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 生成Subject信息
     *
     * @param C  Country Name (国家代号),eg: CN
     * @param ST State or Province Name (洲或者省份)
     * @param L  Locality Name (城市名)
     * @param O  Organization Name (可以是公司名称)
     * @param OU Organizational Unit Name (可以是单位部门名称)
     * @param CN Common Name (服务器ip或者域名)
     * @return X500Name Subject
     */
    public static X500Name generateSubject(String C, String ST, String L,
                                           String O, String OU, String CN) {
        X500NameBuilder x500NameBuilder = new X500NameBuilder();
        x500NameBuilder.addRDN(BCStyle.C, C);
        x500NameBuilder.addRDN(BCStyle.ST, ST);
        x500NameBuilder.addRDN(BCStyle.L, L);
        x500NameBuilder.addRDN(BCStyle.O, O);
        x500NameBuilder.addRDN(BCStyle.OU, OU);
        x500NameBuilder.addRDN(BCStyle.CN, CN);
        return x500NameBuilder.build();
    }
    public static X509Certificate generateV3Certificate(KeyPair pair)
            throws InvalidKeyException, NoSuchProviderException, SignatureException {
        // generate the certificate
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));

        certGen.setNotBefore(new Date(System.currentTimeMillis()));
        certGen.setNotAfter(new Date(System.currentTimeMillis() + (long)1000 * 3600 * 24 * 365));

        // 颁发对象
        X500Name subject2 = generateSubject("CN", "GuangDong", "GuangZhou", "博客:https://blog.csdn.net/penngo", "penngo", "www.penngo.test");
        certGen.setSubjectDN(X509Name.getInstance(subject2));

        // 颁发者
        X500Name subject = generateSubject("CN", "GuangDong", "GuangZhou", "DO_NOT_TRUST", "DO_NOT_TRUST", "Created by penngo");
        certGen.setIssuerDN(X509Name.getInstance(subject));

        certGen.setPublicKey(pair.getPublic());
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");

        certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));

//        certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName(GeneralName.rfc822Name, "test@test.test")));

        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
    }

    public static void main(
            String[] args)
            throws Exception {
        // create the keys
        KeyPair pair = Utils.generateRSAKeyPair();
        PrivateKey aPrivate = pair.getPrivate();
        //下面是私钥key生成的过程
        byte[] privateKeyEncode = aPrivate.getEncoded();
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKeyEncode);
        String privateKeyFileContent = "" +
                "-----BEGIN RSA PRIVATE KEY-----\n" +
                lf(privateKeyStr, 64) +
                "-----END RSA PRIVATE KEY-----";
        FileUtils.write(new File("logs\\server2.key"), privateKeyFileContent,
                StandardCharsets.UTF_8);

        // generate the certificate
        X509Certificate cert = generateV3Certificate(pair);
        // show some basic validation
        cert.checkValidity(new Date());
        cert.verify(cert.getPublicKey());
        byte[] encoded = cert.getEncoded();
        String certStr = Base64.getEncoder().encodeToString(encoded);
        System.out.println("valid certificate generated" + certStr);

        String certFileContent = "" +
                "-----BEGIN CERTIFICATE-----\n" +
                lf(certStr, 64) +
                "-----END CERTIFICATE-----";
        FileUtils.write(new File("logs\\server2.pem"), certFileContent,
                StandardCharsets.UTF_8);
    }
    public static String lf(String str, int lineLength) {
        assert str != null;
        assert lineLength > 0;
        StringBuilder sb = new StringBuilder();
        char[] chars = str.toCharArray();
        int n = 0;
        for (char aChar : chars) {
            sb.append(aChar);
            n++;
            if (n == lineLength) {
                n = 0;
                sb.append("\n");
            }
        }
        if (n != 0)
            sb.append("\n");
        return sb.toString();
    }
}

官方参考自官方例子:https://www.bouncycastle.org/documentation.html
注意当前Java例子生成的证书,在浏览器中会显示不受信任的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1310889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ACM32如何保护算法、协议不被破解或者修改

ACM32具有以下几种功能&#xff0c;可以保护算法、协议不被破解或者修改。 1.存储保护  RDP读保护  WRP写保护  PCROP 专有代码读保护  MPU存储区域权限控制  Secure User Memory存储区域加密 2.密码学算法引擎  AES  HASH  随机数生成  …

DevEco Studio 项目启动工程和Device Manage

DevEco Studio 项目启动工程和Device Manage 鸿蒙&#xff08;HarmonyOS&#xff09; 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、创建虚拟机&#xff08;Device Manage&#xff09; 鸿蒙IDE创建虚拟设备入口有2个地方&…

C++:this指针

目录 前言 成员函数返回this指向的对象本身时&#xff0c;为什是返回引用类型&#xff1f; 成员函数返回this对象本身时&#xff0c;内部通常会通过拷贝构造函数来创建一个临时对象&#xff1f; 总结 前言 c通过提供特殊的对象指针&#xff0c;this指针 指向被调用的成员函…

模块二——滑动窗口:438.找到字符串中所有字母异位词

文章目录 题目描述算法原理滑动窗口哈希表 代码实现 题目描述 题目链接&#xff1a;438.找到字符串中所有字母异位词 算法原理 滑动窗口哈希表 因为字符串p的异位词的⻓度⼀定与字符串p 的⻓度相同&#xff0c;所以我们可以在字符串s 中构造⼀个⻓度为与字符串p的⻓度相同…

每日好题:原来你也玩三国杀(DP动态规划)

I - 原来你也玩三国杀 Description 小 Q 最近听说 “很多” acmer 都爱上了一款游戏《三国杀》。因为小 Q 是一个初学者&#xff0c;所以想自己先偷偷学习一下&#xff0c;然后惊艳所有人。但又因为小 Q 不屑于使用一般的武将&#xff0c;因为他觉得唯有操作型武将才能显得自…

虾皮选品网:如何使用虾皮选品数据软件提升您的选品策略

在虾皮&#xff08;Shopee&#xff09;平台上进行选品时&#xff0c;了解市场趋势、竞争程度和产品潜力是非常重要的。为了帮助卖家更好地分析虾皮市场&#xff0c;并为选品和运营策略提供有力支持&#xff0c;有一些数据软件和工具可以派上用场。本文将介绍一些建议使用的虾皮…

Kafka-集群架构设计

Kafka的Zookeeper元数据梳理 zookeeper整体数据 Kafka将状态信息保存在Zookeeper中&#xff0c;这些状态信息记录了每个Kafka的Broker服务与另外的Broker服务 有什么不同。通过这些差异化的功能&#xff0c;共同体现出集群化的业务能力。这些数据&#xff0c;需要在集群中各个…

DS二分查找_搜索二维矩阵(纯二分查找写法)

本题我写了两个方法&#xff0c;一个是的时间复杂度,就是本文章一个mn时间复杂度&#xff0c;这个比较简单&#xff0c;如果不会二分法可以看这篇文章 Description 使用二分查找法来判断m*n矩阵matrix中是否存在目标值target。 该矩阵有以下特性&#xff1a; 1. 每行中的整数…

智物发布MT6877平台无线AR智能眼镜参考设计,推动下一代无线AR发展

随着增强现实(AR)技术的不断发展&#xff0c;有线AR眼镜在连接和使用方面存在一些限制。为了解决这些问题&#xff0c;无线AR智能眼镜的推出势在必行。 新一代无线AR智能眼镜采用了天玑900&#xff08;MT6877&#xff09;平台作为参考设计&#xff0c;搭载了2.4GHz的八核处理器…

【每日一题】用邮票贴满网格图

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;二维前缀和二维差分 写在最后 Tag 【二维前缀和】【二维差分】【矩阵】【2023-12-14】 题目来源 2132. 用邮票贴满网格图 题目解读 在 01 矩阵中&#xff0c;判断是否可以用给定尺寸的邮票将所有 0 位置都覆盖住&…

飞轮储能一次调频并网三机九节点系统,虚拟惯性和下垂控制,也可加入虚拟同步机VSG控制,飞轮储能容量可调,系统频率50Hz,离散模型

5MW飞轮储能一次调频并网三机九节点系统&#xff0c;虚拟惯性和下垂控制&#xff0c;也可加入虚拟同步机VSG控制&#xff0c;飞轮储能容量可调&#xff0c;系统频率50Hz&#xff0c;离散模型&#xff0c;仿真运行速度快。 飞轮储能变流器采用双PWM环设计&#xff0c;并网电压电…

CleanMyMac2024绿色免费激活码序列号

2024CleanMyMac免费mac下载版是一款简单实用的PC清洁管理工具&#xff0c;电脑刚装完系统的时候运行速度超级快&#xff0c;随着时间的推移&#xff0c;你会发现越来越慢&#xff0c;经常会反应卡顿&#xff0c;越来越多的垃圾文件占用了你的磁盘空间&#xff0c;各种过时的日志…

数据结构学习 12字母迷宫

dfs 回溯 剪枝 这个题和dfs有关&#xff0c;但是我之前没有接触过&#xff0c;我看了这一篇很好的文章&#xff0c;看完之后写的答案。 我觉得很好的总结&#xff1a; dfs模板 int check(参数) {if(满足条件)return 1;return 0; }void dfs(int step) {判断边界{相应操作}尝试…

HPV为什么无症状?皮肤性病科专家谭巍解读具体原因

HPV&#xff0c;即人乳头瘤病毒&#xff0c;是一种常见的性传播疾病。然而&#xff0c;并不是所有感染HPV的人都会出现症状。为什么有的人感染HPV没有症状呢? 首先&#xff0c;需要了解的是&#xff0c;HPV感染是一种非常常见的现象。事实上&#xff0c;大约有80%的性活跃人群…

SLAM学习——相机模型(针孔+鱼眼)

针孔相机模型 针孔相机模型是很常用&#xff0c;而且有效的模型&#xff0c;它描述了一束光线通过针孔之后&#xff0c;在针孔背面投影成像的关系&#xff0c;基于针孔的投影过程可以通过针孔和畸变两个模型来描述。 模型中有四个坐标系&#xff0c;分别为world&#xff0c;c…

智能指针管理“newed对象”

为什么要有智能指针&#xff1f; 指针智能是管理管理动态内存分配对象的一种机制。它提供了自动管理内存&#xff0c;避免常见内存泄漏和悬空指针。 对于上述Func函数的操作&#xff0c;一不小心就会产生很多问题。 p1 new时候抛异常 什么都不做p2 new时候抛异常 p1需要被清理…

SpringBoot 接口实现幂等性,实现的四种方案!

什么是接口幂等性 在HTTP/1.1中&#xff0c;对幂等性进行了定义。它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果&#xff08;网络超时等问题除外&#xff09;&#xff0c;即第一次请求的时候对资源产生了副作用&#xff0c;但是以后的多次请求都不会再对资…

3-分布式存储之Ceph

任务背景 虽然使用了分布式的glusterfs存储, 但是对于爆炸式的数据增长仍然感觉力不从心。对于大数据与云计算等技术的成熟, 存储也需要跟上步伐. 所以这次我们选用对象存储. 任务要求 1, 搭建ceph集群 2, 实现对象存储的应用 任务拆解 1, 了解ceph 2, 搭建ceph集群 3, 了…

【docker】 docker部署minio对象存储并用rclone同步

docker部署minio对象存储并用rclone同步 1.什么是minio&#xff1f; minio是一个开源的对象存储服务器&#xff0c;兼容S3协议。 官网&#xff1a;https://min.io/ 官方在开源的基础上也提供云端S3服务&#xff0c;分为个人和企业&#xff0c;有不同的收费标准。 1.1 自建对…

SQL注入【sqli靶场第15-19关】(四)

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 接上文&#xff1a;SQL注入【sqli靶场第11-14关】(三) …