仓库源文站点原文

密码学入门简明指南

这篇文章不涉及密码学的数学原理,只提及相关概念和应用。 文章的标题改成 应用密码学 可能会更好一点

相关的概念

信息安全

信息安全五要素

各个密码学概念对应的要素

各种攻击所对应的要素

以 https 为例解释信息安全的五要素

信息安全常识

  1. 不要使用保密的密码算法
  2. 使用低强度的密码比不进行任何加密更危险
  3. 任何密码总有一天都会被破解
  4. 密码只是信息安全的一部分

3A

信息安全的基本原则

为了达到信息安全的目标,各种信息安全技术的使用必须遵守一些基本的原则。

随机数

随机数的性质

  1. 随机性,不存在统计学偏差,是完全杂乱的数列
  2. 不可预测性,不能从过去的数列推测出下一个出现的数列
  3. 不可重现性,除非将数列本身保存下来,否则不能重现相同的数列

随机数的分类

随机数的作用

  1. 生成密钥
  2. 生成公钥密码
  3. 生成初始化向量 IV
  4. 生成 nonce
  5. 生成盐

在 linux 下生成随机数

/dev/random 在类 UNIX 系统中是一个特殊的设备文件,可以用作随机数生成器。

/dev/random 的随机数的提供是依赖与外部中断事件的,如果没有足够多中断事件,就会阻塞。 /dev/random 生成的是真随机数。

/dev/urandom(“unblocked”,非阻塞的随机数生成器)是 /dev/random 的一个副本 ,它会重复使用熵池中的数据以产生伪随机数据。 这表示对 /dev/urandom 的读取操作不会产生阻塞,但其输出的熵可能小于 /dev/random 的。 它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。

/dev/random 和 /dev/urandom 会输出二进制数据流,可以用 od 命令转换,或者用 base64 命令转换。

/dev/random 和 /dev/urandom 生成的都是符合密码学安全的随机数。因为 /dev/random 可能会阻塞,所以大部分情况下用 /dev/urandom 就可以了。

大部分情况下都是用 TRNG 生成的随机数作为种子,然后再用 CSPRNG 生成密码学安全的随机数。这样既能保证安全也能效率也不会太低。

命令行下的使用示例

# 不能直接用 cat ,因为 /dev/random 会一直输出
head -n 1 /dev/random | od -x
head -n 1 /dev/urandom | od -x
# 生成随机字符串
head -n 1 /dev/urandom | base64 | head -n 1
head -n 1 /dev/urandom | base64 | head -n 1
# 只生成数字
head -n 1 /dev/urandom | base64 | head -n 1 | tr -dc '0-9'
# 环境变量里的 $RANDOM 是一个随机数字
echo $RANDOM
# 使用 awk 的内置函数
awk 'BEGIN{print rand()}'

在 windows 下生成随机数

windows api

bat 和 powershell

bat

echo %random%

powershell

// 生成一个随机数
Get-Random
// 生成一个小于等于 100 的随机数
Get-Random -Maximum 100
// 在这个范围内 [10.7, 20.93] 生成一个随机数
Get-Random -Minimum 10.7 -Maximum 20.93
// 在这个范围内 [1, 2, 3, 5, 8, 13] 随机选择 3 个数
Get-Random -InputObject 1, 2, 3, 5, 8, 13 -Count 3

x86 汇编生成随机数

RDRAND 指令 和 RDSEED 指令

RDRAND 是英特尔 x86 cpu 中一条用于生成真随机数的指令。

英特尔在 Ivy Bridge 微架构中内置了一个利用电阻热噪声取得硬件真随机数的功能。 后续的 x86 cpu 都支持这个指令。 Ivy Bridge 就是第三代酷睿。 AMD 从哪一款 cpu 开始支持 RDRAND ,笔者没找到详细的资料,但是可以肯定的是 zen 架构及以后的 cpu 型号都支持。 基本可以肯定现在的 x86 cpu 都支持这条指令。 AMD 如何实现 RDRAND ,笔者也没有找到具体的资料,但从一些英文的文章来看, AMD 的 RDRAND 速度似乎比英特尔的要慢不少。

从英特尔的文档来看 RDRAND 和 RDSEED 的区别

RDRAND 和 RDSEED 都有可能调用失败。 英特尔的文档里建议应用程序在紧密循环中尝试 10 次重试,以防 RDRAND 指令不返回随机数。 这个数字基于二项式概率论证:考虑到 DRNG 的设计余量,连续十次失败的几率非常小,实际上表明 CPU 问题更大。

使用内联汇编调用 RDRAND 的例子 只能运行在 x86-64 的 cpu 上,只能运行在 64 位系统上,只能用 gcc 编译

/*
先判断 cpu 是否支持,
    用 CPUID 指令来判断
再判断操作系统的位数,
    用宏定义 __x86_64 来判断
再判断编译器
    如果只是单纯地调用一次 RDRAND 指令,汇编语法用哪个都没关系的
    gcc 或 clang 用 ATT 汇编
    其它用 Intel 汇编
    用宏定义 _MSVCRT_ 来判断
*/
#include <stdio.h>
#include <stdint.h>

#define DRNG_NO_SUPPORT 0x0
#define DRNG_HAS_RDRAND 0x1
#define DRNG_HAS_RDSEED 0x2

typedef struct cpuid_struct {
    unsigned int eax;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;
} cpuid_t;

int get_drng_support();
void cpuid(cpuid_t *info, unsigned int leaf, unsigned int subleaf);
int rdrand16_step(uint16_t *rand);
int rdrand32_step(uint32_t *rand);
int rdrand64_step(uint64_t *rand);

int main()
{
    if (!(get_drng_support() & DRNG_HAS_RDRAND)) {
        printf("\ncurrent cpu is not support rdrand\n");
        return 1;
    }

    uint64_t rand = 0;
    unsigned int retries= 10;
    unsigned int count= 0;
    while (count <= retries) {
        if (!rdrand64_step(&rand)) {
            printf("\ncall rdrand fail\n");
            return 1;
        }
        ++count;
    }

    printf("\nRND64=0x%llx\n", rand);

    return 0;
}

int get_drng_support()
{
    static int drng_features= -1;
    if ( drng_features == -1 ) {
        drng_features= DRNG_NO_SUPPORT;
        cpuid_t info;
        cpuid(&info, 1, 0);
        if ((info.ecx & 0x40000000) == 0x40000000) {
            drng_features|= DRNG_HAS_RDRAND;
        }
        cpuid(&info, 7, 0);
        if ((info.ebx & 0x40000) == 0x40000) {
            drng_features|= DRNG_HAS_RDSEED;
        }
    }
    return drng_features;
}
void cpuid(cpuid_t *info, unsigned int leaf, unsigned int subleaf)
{
    asm volatile("cpuid"
    : "=a" (info->eax), "=b" (info->ebx), "=c" (info->ecx), "=d" (info->edx)
    : "a" (leaf), "c" (subleaf)
    );
}
int rdrand16_step(uint16_t *rand)
{
    unsigned char ok;

    asm volatile ("rdrand %0; setc %1"
        : "=r" (*rand), "=qm" (ok));

    return (int) ok;
}
int rdrand32_step(uint32_t *rand)
{
    unsigned char ok;

    asm volatile ("rdrand %0; setc %1"
        : "=r" (*rand), "=qm" (ok));

    return (int) ok;
}
int rdrand64_step(uint64_t *rand)
{
    unsigned char ok;

    asm volatile ("rdrand %0; setc %1"
        : "=r" (*rand), "=qm" (ok));

    return (int) ok;
}

如果编译器不支持 RDRAND ,可以直接用16进制的指令调用,例如这样

#include <stdio.h>
int main()
{
    long long unsigned int rnd64;
    asm volatile(
        ".byte 0x48,0x0f,0xc7,0xf0\n"
        "ret"
        :"=r"(rnd64):
    );
    printf("\nRND64=0x%llx\n", rnd64);
    return 0;
}

其它生成随机数的方式

可能是因为人们对 混沌系统 研究得不够深入才会觉得 大气噪声 或 电阻热噪声 是随机的 <!-- 如果实在无法使用 硬件 来生成随机数 可以试试用这些方式生成种子 时间 时区 网卡信息 网卡的数量 ip 内网 或 外网 mac地址 操作系统的信息 计算机名 系统版本 内核版本 cpu信息 硬盘信息(硬盘的数量,硬盘的空闲容量) 内存信息(内存的数量,内存的空闲容量) 网速(例如 ping 百度的速度, tracert 百度经过了多少个节点,每个节点的ip这类) 比较推荐 时间+mac地址+硬盘的空闲容量+内存的空闲容量

获取 mac 地址 linux ifconfig windows ipconfig

-->

<!-- TRNG 不是使用数学模型来确定性地生成看起来随机且具有正确统计属性的数字,而是从某种类型的物理源中提取随机性(熵),然后使用它来生成随机数。物理源也称为熵源,可以在使用TRNG的计算系统中自然可用或可用的各种物理现象中进行选择。 单独地使用时间作为随机数的种子违反了 CWE-337 使用较小的种子空间将违反了 CWE-339 在没有 DRNG 之前, linux 是怎么实现 /dev/random ? 为什么总是说伪随机数是不安全的? 伪随机数是如何破解的? CWE Common Weakness Enumeration 常见弱点枚举 CWE 是一项社区驱动的计划,旨在提供常见软件弱点、漏洞和编码错误的标准化且全面的列表。 CWE 由 Mitre Corporation 开发和维护,是网络安全专业人员和软件开发人员的宝贵资源。 还有 CVE 和 CVSS -->

OpenSSL 的一般使用

OpenSSL是一个开放源代码的软件库包。这个包广泛被应用在互联网的网页服务器上。 其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。

以下命令均在 cygwin 或 linux 下运行

以下命令是在这个版本 OpenSSL 1.1.1g 21 Apr 2020 下的 OpenSSL 运行的

openssl req -new \
    -key rsa_private_key.pem \
    -keyform PEM \
    -out myserver.csr
# -new 生成一个新的 csr 文件
# -key 私钥文件路径
# -keyform 私钥的格式
# -out 生成的 csr 文件路径

生成多个域名的证书

一般使用 OpenSSL 生成证书时都是 v1 版的,不带扩展属性。 多域名证书需要用到 v3 版的 extensions 的 Subject Alternative Name (SAN 主题替代名称)

  1. 寻找默认配置文件

    find / -name openssl.cnf
    
  2. 复制一份默认配置文件

    cp /usr/ssl/openssl.cnf openssl.cnf
    
  3. 编辑 openssl.cnf

    1. [ req ] 字段下加入 req_extensions = v3_req
    2. [ v3_req ] 字段下加入 subjectAltName = @alt_names
    3. 在配置文件的最后最后新建一个字段 [ alt_names ]
    4. 在 [ alt_names ] 里按以下格式写入多个域名
       [ alt_names ]
       DNS.1 = 3.example.com
       DNS.2 = 4.example.com
      
  4. 新建私钥

    openssl genrsa -out rsa_private_key.pem 4096
    
  5. 生成 csr 文件

    openssl req -new \
     -key rsa_private_key.pem \
     -keyform PEM \
     -config openssl.cnf \
     -out myserver.csr
    
  6. 生成数字证书

    openssl x509 \
     -sha256 \
     -signkey rsa_private_key.pem \
     -in myserver2.csr \
     -extensions v3_req \
     -extfile openssl.cnf \
     -req -days 365 -out domain.crt
    

自建 CA

  1. 创建 CA 目录

    mkdir -p ~/ssl/demoCA/{certs,newcerts,crl,private}
    cd ~/ssl/demoCA
    Touch index.txt
    echo "01" > serial
    
  2. 寻找默认配置文件

    find / -name openssl.cnf
    
  3. 复制一份默认配置文件

    cp /usr/ssl/openssl.cnf ~/ssl/openssl.cnf
    
  4. 修改 openssl.cnf 文件

  5. 生成 CA 根证书及密钥

    openssl req -new -x509 -newkey rsa:4096 -nodes -keyout cakey.key -out cacert.crt -config openssl.cnf -days 365
    
  6. 生成客户端私钥

    openssl genrsa -out client.key 4096
    
  7. 用该客户端私钥生成证书签名请求

    openssl req -new -key client.key -out client.csr -config openssl.cnf
    
  8. 使用 CA 根证书签发客户端证书

    openssl ca -in client.csr -out client.crt -cert cacert.crt -keyfile cakey.key -config openssl.cnf
    

证书链合并

一些情况下,从 CA 那里申请到的 SSL 证书需要配置证书链,因为颁发的 CA 只是一个中间 CA 。 这个时候,需要把 CA 的证书和 SSL 证书都转换成 pem 格式。 然后新建一个文件,按照 最终实体证书 -> 中间证书 -> 根证书 这样的顺序,把证书的 pem 格式的内容复制进去,证书之间用一个空行隔开。 例如这样

-----BEGIN CERTIFICATE-----
这是 最终实体证书
------END CERTIFICATE------

-----BEGIN CERTIFICATE-----
这是 中间证书
------END CERTIFICATE------

-----BEGIN CERTIFICATE-----
这是 根证书
------END CERTIFICATE------

根证书大多数情况下都会内置在客户端,所以大多数情况下都只需要 最终实体证书 和 中间证书。 有时 中间证书 可能有多个,按照签发顺序排列就好,反正就是下面的证书颁发上面的证书。

有时还需要把私钥和证书合并成一个文件,一般是把私钥放在前面,证书放在后面,例如 这样

cat server.key server.crt > server.pem

其它命令

openssl s_time 用于测试 TSL 服务

openssl s_time -connect www.baidu.com:443 -www /index.html

openssl s_server 用于测试 TSL 客户端,例如浏览器对各个加密套件的支持情况

openssl s_server -accept 2009 -key rsa_private_key.pem -cert domain.crt -www -debug -msg
# -accept 监听的端口 -key 私钥路径 -crt 证书路径 -www http请求返回状态信息
# -WWW 或 -HTTP 参数,则可以启动一个简单的静态服务器
# 如果不设置 -www -WWW -HTTP ,客户端在终端输入任何字符,服务端都会响应同样的字符给客户端
# 可以用浏览器输测试,直接输入网址 https://127.0.0.1:2009
# 可以用 curl 测试 curl -k -i -v https://127.0.0.1:2009
# 可以用 openssl s_client 测试 openssl s_client -connect 127.0.0.1:2009 -showcerts

openssl s_client 用于测试 TSL 服务端

openssl smime 用于处理S/MIME邮件,它能加密、解密、签名和验证S/MIME消息

openssl ca ca命令是一个小型CA系统。它能签发证书请求和生成CRL。它维护一个已签发证书状态的文本数据库。

OpenSSH 的一般使用

OpenSSH (OpenBSD Secure Shell) 是 OpenBSD 的子项目。 OpenSSH 常常被误认以为与 OpenSSL 有关系,但实际上这两个项目有不同的目的,不同的发展团队,名称相近只是因为两者有同样的软件发展目标──提供开放源代码的加密通信软件。

程序主要包括了几个部分:

ssh rsh rlogin rexec 与 Telnet 的替代方案
scp rcp 的替代方案
sftp ftp 的替代方案
sshd SSH服务器
ssh-keygen 产生 RSA 或 ECDSA 密钥,用来认证用
ssh-agent ssh-add 帮助用户不需要每次都要输入密钥密码的工具

以下命令是在这个版本 OpenSSH_8.5p1, OpenSSL 1.1.1k 25 Mar 2021 下的 OpenSSH 运行的

sshd

ssh

ssh 的端口转发

ssh 除了登录服务器,还有一大用途,就是作为加密通信的中介, 充当两台服务器之间的通信加密跳板, 使得原本不加密的通信变成加密通信。 这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。

ssh 的端口转发有三种

ssh 文档 https://man.openbsd.org/ssh

https://wangdoc.com/ssh/port-forwarding

sftp

OpenSSH 和 OpenSSL

OpenSSH 是 SSH 协议的实现,实现过程中,需要用到密钥交换算法,对称/非对称加密算法,随机数算法,等密码学相关的算法。 早期版本的 OpenSSH 是通过调用 OpenSSL 的库来实现这些算法的。 2014年4月的心脏出血漏洞事件之后, OpenBSD 项目成员以 OpenSSL 1.0.1g 作为分支,创建一个名为 LibreSSL 的项目。 OpenSSH 会逐渐减少对 OpenSSL 的依赖。

GnuPG 的一般使用

1991 年,程序员 Phil Zimmermann 为了避开政府的监视,开发了加密软件 PGP (Pretty Good Privacy)。 但是,它是商业软不能自由使用。所以,自由软件基金会决定,开发一个 PGP 的替代品取名为 GnuPG (GNU Privacy Guard)。 OpenPGP (Pretty Good Privacy) 是一种加密标准。 GnuPG 是实现该标准的软件。

gpg 在需要用到私钥的地方都需要口令。 gpg 会对消息进行压缩。

gpg 的配置文件一般会保存在这个位置

linux ~/.gnupg
windows 系统盘/Users/用户名/.gnupg

加密和解密

签名和验签

一些命令参考

以下命令是在这个版本 gpg (GnuPG) 2.2.28 下的 GnuPG 运行的

GnuPG 和 email

很多邮件客户端都支持使用 GPG 来加密邮件。

只要导入发件人的私钥和收件人的公钥,就能发送加密的邮件。发件人的邮箱地址需要和私钥的邮箱地址对应,收件人的邮箱地址需要和公钥的邮箱地址对应。 使用加密后,会把整个邮件报文加密,包括主题,然后把密文保存在一个文件里,作为附件发送。 如果收件人的邮件客户端不支持直接解密邮件,可以把邮件的附件下载下来然后再用 GPG 解密。像这样 gpg --recipient [接收者ID] --output demo.de.txt --decrypt encrypted.asc

其实把明文加密后再把密文复制到邮件内容里发送也可以,但收件人的邮件客户端未必能解密,因为一般加密的邮件都是整个报文加密的,这种可能需要把邮件里的密文保存到单独的文件后再解密。

参考

https://zh.wikipedia.org/wiki/%E5%85%AC%E9%92%A5%E5%AF%86%E7%A0%81%E5%AD%A6%E6%A0%87%E5%87%86

https://zh.wikipedia.org/wiki/%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8

https://yeasy.gitbook.io/blockchain_guide/ 区块链技术指南 虽然是讲区块链的,但密码学部分很有参考价值

https://book.douban.com/subject/26822106/ 图解密码技术(第3版)

https://www.gnupg.org/howtos/zh/index.html GnuPG 袖珍 HOWTO (中文版)

https://docs.azure.cn/zh-cn/articles/azure-operations-guide/application-gateway/aog-application-gateway-howto-create-self-signed-cert-via-openssl

https://www.crypto101.io/ 密码学入门课程

<!-- 除了 openssl 之外还有很多加密库 guntls libsodium Bouncy Castle LibreSSL Bouncy Castle 是用于在计算机程序中实现加密的 API 集合。 它包括用于 Java 和 C# 编程语言的 API。 这些 API 由澳大利亚注册的慈善组织 Legion of the Bouncy Castle Inc. 提供支持。 Bouncy Castle 起源于澳大利亚,因此美国对从美国出口密码学的限制不适用于它。 同态加密? 密码学原语? 哈希承诺? 秘密分享(Secret Sharing)? 门限加密? 门限签名? 差分隐私? Feistel 密码结构 国密 线性同余方法(Linear Congruence Generator , LCG) Web Crypto API https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API 密码朋克 证书透明度(Certificate Transparency,CT) Merkle 树 梅克尔树或默克尔树 是 哈希数 也是 二叉树 证书签署时间戳 signed certificate timestamp (SCT) 字体加密 量子信息 量子计算 量子计算机 量子通讯 量子密码 证书链的验证过程 数字摘要 文件的 字符串的 随机数 对称加密 解密 生成 rsa 密钥 rsa 的加密 解密 rsa 签名 验签 生成 csr 生成证书 自建 ca 生成一个 csr 文件,启动一个问题/回答的交互式会话,其中 Common Name 那里就是填域名的,其它随便填就好,'extra' attributes 留空 openssl req -new \ -key rsa_private_key.pem -keyform PEM \ -out myserver.csr Common Name 只适用于单个域名或单个泛解释的域名 单个泛解释的域名,如果 Common Name 是 *.baidu.com ,那么 b.baidu.com 是有效的,但 a.b.baidu.com 是无效的 如果要多个域名就需要有 使用者可选名称 或者 使用者备选名称 这个字段 这个属于拓展属性 自建 ca 证书链的验证过程 openssl req -new \ -sha256 \ -key rsa_private_key.pem -keyform PEM \ -out myserver2.csr \ -subj /C=US/ST=Illinois/L=Chicago/O=FaultyConsulting/OU=IT/CN=myserver.com 在Windows平台使用Git执行bash脚本生成SSL证书时,以下命令会产生错误Subject does not start with '/': openssl req -new -x509 -days 365 -key ca_private.key -out ca_cert.crt -subj "/C=CN/ST=BJ/L=BJ/O=abc/OU=abc/CN=abc/emailAddress=abc@abc.com" 该错误是由Git for Windows中MinGW/MSYS模块的路径转换机制引起的。 解决方案:将-subj参数中第一个“/”改为“//”,其余“/”改为“\”,如下: -subj "//C=CN\ST=BJ\L=BJ\O=abc\OU=abc\CN=abc\emailAddress=abc@abc.com" openssl req -newkey rsa:4096 -nodes \ -keyout rsa_private_key.pem -x509 \ -days 365 \ -out domain.crt \ -subj "//C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=localhost" 但按上面的方式生成的证书没有 C 这个字段 会有这样的提示 req: Skipping unknown attribute "/C" openssl req -newkey rsa:4096 -nodes \ -keyout rsa_private_key.pem -x509 \ -days 365 \ -out domain.crt \ -subj "//A=1/C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=localhost" 在最前面加一个无效的字段,像是 //A=1 这样 虽然会有这样的提示,但没有关系的 req: Skipping unknown attribute "/A" 用这样的命令查看证书内容 openssl x509 -in domain.crt -noout -text https = http + ssl 或 http + stl http + ssl 已经被弃用 现在的都是 http + stl 有些时候也会称为 http + TLS/SSL wss = websocket + TLS/SSL 网景公司(Netscape)在1994年推出首版网页浏览器-网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源 IETF将SSL标准化,并将其称为TLS(Transport Layer Security),1999年公布TLS 1.0标准文件(RFC 2246) 传输层安全性协议(英语:Transport Layer Security,缩写:TLS) 及其前身安全套接层(英语:Secure Sockets Layer,缩写:SSL) 是一种安全协议 数字证书的详细内容,特别是 ssl 证书的内容 CA/B论坛将国际主流CA签发的证书通过证书审核的内容划分为3种类型,分别是:DV,OV,EV类型。 DV Domain Validation Certificate 域名验证证书 OV Organization Validation Certificate 组织验证证书 EV Extended Validation Certificate 扩展验证证书 单域名证书 多域名证书 通配符证书 域名验证型证书和扩展验证证书的区别在于,认证域名是签发域名验证型证书的唯一要求。,但无法向用户证明网站的真实身份。 组织验证型证书,既要验证域名所有权,也要验证企业或组织身份,安装OV证书后,既能保证加密传输,也能证明网站的真实身份,安全性和可信任度更高。 只有通过独立的网络信任审核的证书发行机构才能颁发扩展验证证书,全球范围内的证书发行机构都必须遵循同样详细的签发要求以便于: 确认网站及其所有者的合法性; 确认申请者是对应网站的域名持有人并且可以独立地控制该域名; 确认网站持有者的身份并且审查由具有相应权限的政府官员签发的有关其法律义务的文件。 另外,扩展验证证书中不能包含通配符。 EV证书因为其采用了更加严格的认证标准 审核过程可能牵涉专业法律人员的调查及独立审计人员的确认 审核严格:申请EV SSL证书时,CA机构不仅需要对域名所有权及网站企业身份进行严格审查,还增加了第三方严格身份审核,确保证书持有组织的真实性。所谓的第三方身份审核,指的是需要有权威的第三方进行担保 DV OV 包含企业名称信息 否 是 验证公司名称合法性 否 是 通过第三方查询电话验证 否 是 域名验证方式 管理员邮箱批准 查询whois信息是否一致 验证时间 最快10分钟签发 一般2-3天完成签发 证书可信度 低 较高 DV和OV型证书在用户查看证书的详情是,OV型证书会在证书的Subject中显示域名+单位名称等信息;DV型证书只会在证书的Subject中显示域名 证书颁发机构浏览器论坛,也称CA/浏览器论坛(英语:CA/Browser Forum)、证书机构与浏览器论坛,它是一个证书颁发机构、网页浏览器软件供应商、操作系统,以及其他采用PKI的应用程序的自愿联合体,其颁布X.509 v.3电子证书的签发与管理的行业治理方针,在诸多应用程序中链接到信任锚。其方针涵盖用于SSL/TLS协议和代码签名的证书,以及系统和证书颁发机构的系统和网络安全。 截至2014年10月,CA/浏览器论坛维护“扩展验证(EV)证书的颁发和管理的指导方针”。EV SSL标准改善了互联网交易的安全性,并创造了一种更直观的向互联网用户表示安全网站的方法。颁发EV SSL证书的证书颁发机构必须接受审计,以符合论坛的EV方针[1]WebTrust或ETSI审核标准的。 CA/浏览器论坛于2011年通过了“公共可信证书颁发和管理的基线要求”。这些方针对CA/浏览器论坛成员具有约束力,自2012年7月1日起生效。这些方针涵盖了CA颁发的所有证书。证书现分类为“DV”(域名验证),“OV”(组织验证)、“IV”(个体验证)和“EV”(扩展验证),并在该规范中定义了一种方法区分证书类型的方法。 证书透明度(英语:Certificate Transparency,简称CT)也称证书透明、证书透明化,它是一个实验性的IETF开源标准[1]和开源框架,目的是监测和审计数字证书。通过证书日志、监控和审计系统,证书透明度使网站用户和域名持有者可以识别不当或恶意签发的证书,以及识别数字证书认证机构(CA)的作为。 HTTP over SSL 或 HTTP over TLS Stunnel 安装 debian apt-get install -y stunnel windows/安卓 从官网里下载安装 https://www.stunnel.org/downloads.html 文档 https://www.stunnel.org/docs.html 配置文件的例子 https://www.stunnel.org/examples.html github https://github.com/mtrojnar/stunnel 配置 服务端 创建 psk.txt 的文件, password 可以是很长的字符串,password 长度要大于 16 user1:password1 user2:password2 创建 stunnel.conf 文件 ; 指定 ssl 版本 sslVersion = TLSv1.3 ; 自定义的服务名 [mysql] ; 服务监听的端口, client 要连接这个端口与 server 通信 accept = 13069 ; 服务要连接的端口 connect = 172.31.22.12:3306 ciphers = PSK PSKsecrets = psk.txt 客户端 创建 psk.txt 的文件,需要和服务端里的 psk.txt 里的某一行一致 user1:password1 创建 stunnel.conf 文件 ; 指定 ssl 版本 sslVersion = TLSv1.3 ; 自定义的服务名 [mysql] client = yes ; 监听 3128 端口,那么用户浏览器的代理设置就是 stunnel-client-ip:3128 accept = 3128 ; 要连接到的 stunnel 服务端的 IP 和端口 connect = xx.xx.xx.xx:3129 PSKsecrets = psk.txt 客户端与服务端配置的区别就是多了一个 client = yes 的配置项 运行 服务端 stunnel stunnel.conf 客户端 stunnel stunnel.conf 服务端 客户端 运行的命令是一样的, psk.txt 和 stunnel.conf 最好放在同一个目录下 stunnel 会直接在后台运行,退出 stunnel 可以用 ps 找到对应的 pid 然后 kill ,像这样 ps -elf | grep stunnel kill pid 例子 使用 stunnel 实现的 https 0. 安装 stunnel openssl python 0. 开放 80 和 443 端口 0. 运行 python 一句话服务器 python -m http.server -b 0.0.0.0 80 0. 新建一个测试用的文件 echo hello > index.html 0. 生成私钥和证书 openssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt -subj "/C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=localhost" 0. 新建配置文件 stunnel.conf [http2https] key=rsa_private_key.pem cert=domain.crt accept=443 connect=127.0.0.1:80 0. 运行 stunnel stunnel stunnel.conf 0. 在浏览器分别访问 http://localhost https://localhost 使用 stunnel 实现加密的 telnet 0. 假设 telnet 的连接地址是 telnetserver 23 0. 在服务端安装 stunnel 0. 生成私钥和证书 openssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt -subj "/C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=telnetserver" 0. 新建配置文件 stunnel.conf [telnet2telnets] key=rsa_private_key.pem cert=domain.crt accept=992 connect=127.0.0.1:23 0. 运行 stunnel stunnel stunnel.conf 0. 在客户端直接用 telnets 连接 telnets telnetserver 992 0. 在客户端安装 stunnel ,然后用 telnet 连接 0. stunnel 的客户端配置文件 [telnet] client=yes accept=992 connect=telnetserver:992 0. 启动 stunnel 后,用 telnet 这样连接 telnet localhost 992 stunnel 和代理服务配合使用 0. 假设代理服务的连接地址是 socks5://127.0.0.1:1080 生成私钥和证书 openssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt -subj "/C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=telnetserver" 从私钥中提取公钥 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem sslVersion = TLSv1.3 [proxy] key=rsa_private_key.pem cert=domain.crt accept=443 connect=127.0.0.1:1080 sslVersion = TLSv1.3 [proxy] client=yes accept=1080 connect=服务端地址:443 验证代理是否有生效 curl -i -v -L --proxy socks5://127.0.0.1:1080 https://www.baidu.com 关注一开始是否有 socks5 代理的输出 关注 tls 的版本和密码套件 SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 使用 psk 应该是可以的。。。再试一次 psk 确实是有效的,但似乎不能用 tls1.3 虽然能成功连接,但没有客户端验证 客户端验证似乎还需要更复杂的配置 ciphers 是设置 tls1.2及以下版本的 ciphersuites 这个才是设置 tls1.3 的 其实 stunnel 能直接支持 socks5 代理,不需要额外的代理软件 stunnel 的 socks5 代理 服务端设置 output=/var/log/stunnel.log ; 要指定日志输出的位置,不然日志会直接输出到当前终端里 syslog=no ; 不使用 syslog 记录日志 [proxy] debug=4 ; 降低调试级别,减少日志 ciphers = PSK PSKsecrets = psk.txt accept=:::443 protocol = socks 客户端设置 output=/var/log/stunnel.log syslog=no [proxy] debug=4 client=yes accept=1080 connect=服务端地址:443 PSKsecrets = psk.txt 一些配置是 unix only ,一些配置是 win32 only ,所以还是要认真看一下文档 https://www.stunnel.org/static/stunnel.html stunnel 虽然以 GPL2 开源,但似乎不能免费地商用 -->