这篇文章不涉及密码学的数学原理,只提及相关概念和应用。
文章的标题改成 应用密码学 可能会更好一点
古典密码 基于字符的替换或移项,或者两者混合使用。
现代密码 使用计算机技术的,在比特和字节上操作。
明文 = 在密码学中是指传送方想要接收方获得的可读信息
密文 = 经过加密的明文
加密 = 把明文转换为密文的过程
解密 = 把密文转换为明文的过程
密钥 = 指某个用来完成加密、解密、完整性验证等密码学应用的秘密信息
密码 约等于 密钥
Hash = 哈希,又被翻译为 离散
数字摘要 = 一段信息的哈希值,一般情况下是指明文的哈希值
MD = 消息摘要 (Message Digest) ,就是数字摘要
OWF = 单向函数(One-Wayness Function) ,单向函数是一种容易计算同时难以求逆的函数。通常使用在消息摘要里。 哈希函数就是一种单向函数
OWF = 单向函数(One-Wayness Function) ,单向函数是一种容易计算同时难以求逆的函数。通常使用在消息摘要里。 哈希函数就是一种单向函数
MAC = 消息验证码 (Message Authentication Code) ,就是明文 + 密钥 + MAC 算法生成的一段数据,这里的密钥一般是对称加密的密钥,MAC 算法有很多种,但最常用的是 hash 算法,就是明文加上密钥的数字摘要
HMAC = 使用 hash 算法的 MAC
Nonce 是 Number used once 或 Number once 的缩写,数字使用一次,在密码学中 Nonce 是一个只被使用一次的任意或非重复的随机数值
时间戳 timestamp 表示的是从世界标准时间(UTC,Coordinated Universal Time)的 1970 年 1 月 1 日 0 时 0 分 0 秒开始到现在的秒数,时间戳大部分情况下是 10 位的,但有时也会用 13 位的时间戳
块加密 (block cipher) 又称为 分块加密 或 分组加密 ,是将明文分成多个等长的模块(block),使用确定的算法和对称密钥对每组分别加密解密。块加密通常有三个参数,算法 密码强度 模式,例如 aes-256-gcm , aes 是对称加密的算法, 256 是密码强度, gcm 是分组密码的工作模式,通常只有块加密的算法有工作模式的参数。DES 和 AES 都是块加密
流加密 (stream cipher) 加密和解密双方使用相同伪随机加密数据流(pseudo-randomstream)作为密钥,明文数据每次与密钥数据流顺次对应加密,得到密文数据流。实践中数据通常是一个位(bit)并用异或(xor)操作加密。RSA 是流加密
对称加密 = 加密和解密都用同一个密钥。
非对称加密 = 加密和解密使用不同的密钥。
公开密钥密码学 (Public-key cryptography) 就是 非对称加密
公钥 = 在非对称加密中,可以公开的密钥
私钥 = 在非对称加密中,不能公开的密钥
数字签名 = 在非对称加密中,由私钥和签名算法生成的信息。在 RSA 中数字签名是由私钥加密后的数字摘要,但其它非对称加密算法不是这样的。
密钥密文 一般是指,对称加密和非对称加密组合使用下,使用公钥 加密 对称加密的密钥
数字信封 一般是指,对称加密和非对称加密组合使用下,内容是 密钥密文 + 密文 (使用对称加密的密文) 的信息。数字信封既发挥了对称加密算法速度快的优点,又发挥了非对称加密算法密钥管理方便的优点。
CEK = 内容密钥 (Contents Encrypting Key) ,就是用于加密明文的密钥,是和 KEK 相对的
KEK = 加密密钥的密钥 (Key Encrypting Key)
PBE = 基于口令的密钥 (Password Based Encryption,PBE) ,在 PGP 里会用 PBE 加密私钥
盐(Salt),在密码学中,是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。在大部分情况,盐是不需要保密的。盐可以是随机产生的字符串,其插入的位置可以也是随意而定。
数字证书 = 用户信息(csr) + 用户公钥 + 公钥指纹 + 其它相关信息 + (颁发机构私钥 加密 前面提及的 相关数据的 数字摘要 所得到的数字签名)
证书
版本号
序列号 由证书颁发者分配的本证书的唯一标识符。颁发者和证书序列号配合起来就能唯一地标识一张数字证书。
签名算法
颁发者
国家(C,Country)
州/省(S,State)
地域/城市(L,Location)
组织/单位(O,Organization)
通用名称(CN,Common Name)
证书有效期
此日期前无效
此日期后无效
主题
国家(C,Country)
州/省(S,State)
地域/城市(L,Location)
组织/单位(O,Organization)
通用名称(CN,Common Name) 在 TLS 应用上,此字段一般是域名
主题公钥信息
公钥算法
主题公钥
颁发者唯一身份信息(可选项 AKID , authority key identifier ) 颁发者公钥的数字摘要
主题唯一身份信息(可选项 SKID , subject key identifier ) 主题公钥的数字摘要
扩展信息(可选项)
主题别名(Subject Alternative Name) 在 TLS 应用上,如果一个证书需要支持多个域名,则其它域名会填在这里
授权密钥标识符 颁发者的公钥
...
证书签名算法
数字签名
PKC = 公钥证书 (Public-Key Certificate,PKC) ,就是数字证书
公钥指纹 = 公钥的数字摘要,是用于标识较长公共密钥字节的短序列。由于指纹较比生成它们的密钥短得多,因此可以用来简化某些密钥的管理任务。
颁发证书 = CA 用私钥加密 CSR 和 用户公钥然后生成数字证书的过程
csr 是 cerificate signing request 的英文缩写,即证书请求文件,内容是 公钥 + 用户信息(例如 域名之类的),一般是向 CA 申请数字证书用的。 X.509 证书申请的格式标准为 PKCS10 和 rfc2314 。 cerificate 证书 signing 签署 request 请求
CA = 数字证书认证 (Certificate Authority)
CA 中心 = 数字证书认证机构,一般情况下 CA 和 CA 中心 都是指 数字证书认证机构
CA 系统 = 用于颁发数字证书的系统,由 CA 中心管理和运营
CAA = 数字证书认证授权 (Certificate Authority Authorization) , CAA 是一种 DNS 记录,它允许站点所有者指定允许哪些证书颁发机构(CA)颁发包含其域名的证书。
crt 和 cert 都是 certificate 的缩写
最终实体证书 = 普通用户向 CA 申请后使用的证书
自签证书 = 用户信息(csr) + 用户公钥 + 私钥加密前面两个数据所得到的数字签名(用户私钥)
证书链是从终端用户证书后跟着一系列的 CA 证书,而通常最后一个是自签名证书,并且有如下关系:
根证书 = 证书链里最后一个证书,一般是自签证书,一般是 CA 的自签证书,根证书一般是直接内置在客户端(内置在浏览器或操作系统里)的
中间证书 = 一个 CA 向另一个 CA 颁发的证书,又或者说证书链中处于中间位置的证书,一个证书链里可以有多个中间证书
在线证书状态协议(英语:Online Certificate Status Protocol,缩写:OCSP)是一个用于获取 X.509 数字证书撤销状态的网际协议,在RFC 6960中定义,作为证书吊销列表(CRL)的替代品解
证书吊销列表(英文:Certificate revocation list,缩写:CRL,或译作证书废止清册)是尚未到期就被证书颁发机构吊销的数字证书的名单。这些在证书吊销列表中的证书不再会受到信任。目前,在线证书状态协议(OCSP)已经替代证书吊销列表(CRL)成为检查证书状态的主流。
证书链的验证
PKI = 公开密钥基础设施 (Public Key Infrastructure) , PKI 包含 PKIX 和 PKCS
PKCS = 公钥密码学标准 (The Public-Key Cryptography Standards)
X.509 = PKIX
PKIX = 公钥基础设施 X.509 (Public Key Infrastructure X.509) ,X.509 是密码学里公钥证书的格式标准,证书组成结构标准用 ASN.1 来进行描述
X.509 是密码学里公钥证书的格式标准, PKCS 是一系列密码学的标准, PKCS 有十几个标准, X.509 大致相当于 PKCS1 和 PKCS12
PKCS #12 定义了一种存档文件格式,用于实现存储许多加密对象在一个单独的文件中。通常用它来打包一个私钥及有关的 X.509 证书,或者打包信任链的全部项目。一个 PKCS #12 文件通常是被加密的,同时单独存在(存档文件格式)。
PFX = PKCS#12 ,其实也不算是严格相等,但大多数语境下可以相等
PKCS 比较常用的是 1 7 8 10 12
ASN.1 抽象语法符号 (Abstract Syntax Notation One,ASN.1)
DER = 可辨别编码规则 (Distinguished Encoding Rules) ,是一种二进制的用于保存证书和密钥的文件编码格式, windows 和 java 是用这种格式的
PEM = 私密 增强 邮件 (Privacy Enhanced Mail) ,是一种纯文本的用于保存证书和密钥的文件编码格式,而 DER 编码的内容是二进制的,不适合与邮件传输(早期 email 不能发送附件), nginx apahce php 是用这种格式的
JKS = Java Key Storage, JAVA 的专属格式,利用 JAVA 的一个叫 keytool 的工具可以进行格式转换。一般用于 Tomcat 服务器。
PKCS 和 X.509 是格式标准,而 DER 和 PEM 是文件编码格式
CA/浏览器论坛 (CA/Browser Forum) ,是一个证书颁发机构、网页浏览器软件供应商、操作系统,以及其他采用PKI的应用程序的自愿联合体,其颁布X.509 v.3电子证书的签发与管理的行业治理方针,在诸多应用程序中链接到信任锚。其方针涵盖用于SSL/TLS协议和代码签名的证书,以及系统和证书颁发机构的系统和网络安全。
会话密钥,加密会话内容的密钥,大多数情况下只用一次。
主密钥,会被重复使用的,加密会话密钥的密钥。
PSK = 预共享密钥 (pre-shared key)
常用的算法
密码套件 (cipher suite) 或者称为密码包,是 https 中各种算法的集合,一般包括 密钥交换算法 身份验证算法 加密算法(加密方法-加密强度-模式) 哈希算法 。一般情况下密码包里的算法不能重复出现,例如 密钥交换算法用了 RSA ,那么身份验证算法就不能用 RSA
PR = 伪随机数 (Pseudo Random) ,计算机里生成真正的随机数其实挺麻烦的,所以一般都是用伪随机数
PRF = 伪随机数函数 (Pseudo Random Function) ,就是用于生成伪随机数的方法
PRP = 伪随机置换 (Pseudo Random Permutation)
PRNG = 伪随机数生成器 (Pseudo Random Number Generator) ,就是用于生成伪随机数的方法
TRNG = 真随机数生成器 (True Random Number Generator)
HRNG = 硬件随机数生成器 (Hardware Random Number Generator) ,大部分语境下 HRNG == TRNG ,单靠软件无法生成真随机数
CSPRNG = 密码学安全伪随机数生成器 (Cryptographically secure pseudo-random number generator)
TTP 可信赖的第三者 (Trusted third party) ,在 PKI 里通常是指 CA
OTP 一次性密码本 (one-time pad)
HTTPS = HTTP + TLS 或 HTTP + TLS , HTTP + SSL 已经被弃用,现在的都是 HTTP + TLS ,有些时候也会称为 HTTP + TLS/SSL
WSS = WebSocket + TLS/SSL
SSL = 安全套接层 (Secure Sockets Layer) ,网景公司(Netscape)在 1994 年推出首版网页浏览器-网景导航者时,推出 HTTPS 协议,以 SSL 进行加密
TLS = 传输层安全性协议 (Transport Layer Security) , IETF 将 SSL 标准化,并将其称为 TLS , 1999 年公布 TLS 1.0 标准文件(RFC 2246)。其实大多数 TCP 的协议都可以在上面套一层 TLS
除了 HTTP 之外 TSL/TLS 可以跟很多常用的应用层协议(比如:FTP、SMTP、POP、Telnet)搭配使用
TLS 服务器证书,就是启用 HTTPS 时需要用到的数字证书,也称为 SSL 证书,一般是从 CA 申请后部署在 HTTP 服务器的
一般语境下的 SSL 证书,就是 Common Name 是域名的数字证书
S/MIME ,安全的多用途 Internet 邮件扩展(Secure Multipurpose Internet Mail Extensions,简称S/MIME)是一种 Internet 标准,它在安全方面对 MIME 协议进行了扩展,可以将 MIME 实体(比如数字签名和加密信息等)封装成安全对象,为电子邮件应用增添了消息真实性、完整性和保密性服务。 S/MIME 不局限于电子邮件,也可以被其他支持 MIME 的传输机制使用,如 HTTP
证书颁发机构浏览器论坛,也称 CA/浏览器论坛(英语: CA/Browser Forum 缩写: CA/B)、证书机构与浏览器论坛,它是一个证书颁发机构、网页浏览器软件供应商、操作系统,以及其他采用 PKI 的应用程序的自愿联合体,其颁布 X.509 v.3 电子证书的签发与管理的行业治理方针,在诸多应用程序中链接到信任锚。其方针涵盖用于 SSL/TLS 协议和代码签名的证书,以及系统和证书颁发机构的系统和网络安全。
证书透明度(英语:Certificate Transparency,简称CT)也称证书透明、证书透明化,它是一个实验性的IETF开源标准和开源框架,目的是监测和审计数字证书。通过证书日志、监控和审计系统,证书透明度使网站用户和域名持有者可以识别不当或恶意签发的证书,以及识别数字证书认证机构(CA)的作为。
向前保密,前向安全性或前向保密性(英语:Forward Secrecy,缩写:FS),有时也被称为完美前向安全(英语:Perfect Forward Secrecy,缩写:PFS),是密码学中通讯协议的安全属性,指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。
零知识证明(Zero Knowledge Proof),是这样的一个过程,证明者在不向验证者提供任何额外信息的前提下,使验证者相信某个论断(Statement)是正确的。证明过程包括交互式(Interactive)和非交互式(Non-interactive)两种。
各类编码的转换,例如 base64 和 urlencode ,这类编码的转换虽然可以把一般的字符串转换成一堆看上去是乱码的字符串,但实质上并没有加密的功能,只是增加了普通人的阅读障碍。有些时候也可以用这类方式来规避一些内容的审查
数字指纹 主要用于版权保护,其研究具有重要的意义。数字指纹是将不同的标志性识别代码——指纹,利用数字水印技术嵌入到数字媒体中,然后将嵌入了指纹的数字媒体分发给用户。发行商发现盗版行为后,就能通过提取盗版产品中的指纹,确定非法复制的来源,对盗版者进行起诉,从而起到版权保护的作用。
e2ee 端到端加密 (End-to-end encryption) 是一种只有参与通讯的用户可以读取信息的通信系统。总的来说,它可以防止潜在的窃听者——包括电信供应商、互联网服务供应商,获取能够用以解密通讯的密钥。此类系统被设计为可以防止潜在的监视或篡改企图,因为没有密钥的第三方难以破译系统中传输或储存的数据。
SSH = Secure Shell
DoH 和 DoT
DNSSEC = 域名系统安全扩展(DNS Security Extensions),简称DNSSEC。通过数字签名来保证 DNS 应答报文的真实性和完整性,能够防止 DNS 欺骗和缓存污染等攻击。
TOTP = Time-based One-time Password (基于时间的一次性密码) 。RFC 6238
UUID = Universally Unique Identifier (通用唯一识别码)
DCE = Distributed Computing Environment (分布式计算环境)
口令 密码 密钥 令牌 的区别
会议
https 的连接过程
数字证书和证书链是保证信息源的真实性
为了达到信息安全的目标,各种信息安全技术的使用必须遵守一些基本的原则。
/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()}'
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
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是一个开放源代码的软件库包。这个包广泛被应用在互联网的网页服务器上。 其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。
以下命令均在 cygwin 或 linux 下运行
以下命令是在这个版本
OpenSSL 1.1.1g 21 Apr 2020
下的 OpenSSL 运行的
查看 openssl 的版本信息
openssl version -a
查看帮助,这里会输出 openssl 支持的算法
openssl help
查看某个命令的帮助
openssl 某个命令 --help
查看密码套件
openssl ciphers -v
数字摘要
echo "123" | openssl dgst -sha256
openssl dgst -sha256 文件路径
echo "123" | openssl dgst -sha256 | awk '{print $2}'
openssl dgst -sha256 文件路径 | awk '{print $2}'
输出当前时间戳
# 10位时间戳
date +%s
# 13位时间戳
date +%s%3N
输出纳秒 这是一个 9 位的数字 一些简单的伪随机数算法会使用纳秒作为种子
date +%N
生成 32 位随机字符串
openssl rand -base64 32
openssl rand -base64 256 | sed ':a;N;$!ba;s/\r\n/\n/g' | sed ':a;N;$!ba;s/\n//g' | tr -dc [:alnum:] | cut -c1-32
输出随机数字
# 输出随机数字,但无法确定数字的长度
openssl rand -base64 32 | tr -dc '0-9'
openssl rand -base64 64 | tr -dc '0-9'
# 生成16位随机数 有可能不足16位
openssl rand -base64 128 | tr -dc '0-9' | cut -c1-16
# 生成16位随机数
openssl rand -base64 128 | sed ':a;N;$!ba;s/\r\n/\n/g' | sed ':a;N;$!ba;s/\n//g' | tr -dc [:digit:] | cut -c1-16
查看 对称加密命令和可以使用的算法
openssl enc -help
enc 使用对称加密算法
openssl enc -aes-256-cfb -e -in a.txt -a -out b.txt -pass pass:123
openssl enc -aes-256-cfb -d -in b.txt -a -out c.txt -pass pass:123
# -aes-256-cfb 使用的算法
# -e 加密
# -d 解密
# -in 输入的文件路径
# -out 输出文件的路径
# -a 把输出转换成 base64 加密时有这个参数,解密时也要有这个参数
# -pass 数入密码和输入密码的方式
# pass
# file
# stdio
# env
# fd
生成 rsa 私钥
openssl genrsa -out rsa_private_key.pem 4096
# 默认是 pem 格式的
# -out 指定生成文件的路径
# 最后的 4096 是生成密钥的长度
# 生成的密钥对是 pkcs1 格式的, openssl 有相应的命令转成 pkcs8 或 pkcs12 格式
从私钥中提取公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
# -pubout 提取公钥
# -out 指定生成文件的路径
# -in 私钥路径
公钥加密文件
openssl rsautl -encrypt -in a.txt -inkey rsa_public_key.pem -pubin -out b.txt
# -out 加密后的文件路径
# -in 需要加密的文件路径
# -inkey 公钥路径
私钥解密文件
openssl rsautl -decrypt -in b.txt -inkey rsa_private_key.pem -out c.txt
# -out 解密后的文件路径
# -in 需要解密的文件路径
# -inkey 私钥路径
使用私钥生成签名
openssl dgst -sha256 -sign rsa_private_key.pem -keyform PEM -out sign.sha256 a.txt
# -sha256 哈希算法
# -sign 私钥路径
# -keyform 私钥的格式
# -out 签名生成的路径
# 最后的 a.txt 是需要生成签名的文件路径
使用公钥验证签名
openssl dgst -sha256 -verify rsa_public_key.pem -keyform PEM -signature sign.sha256 a.txt
对文件的内容进行 base64 编码
openssl enc -base64 -e -in sign.sha256 -out sign.sha256.base64
对文件的内容进行 base64 解码
openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha2562
比较两个文件的内容,如果两个文件内容一致则不会有输出
diff 文件1的路径 文件2的路径
生成一个 csr 文件
openssl req -new \
-key rsa_private_key.pem \
-keyform PEM \
-out myserver.csr
# -new 生成一个新的 csr 文件
# -key 私钥文件路径
# -keyform 私钥的格式
# -out 生成的 csr 文件路径
查看 csr 文件内容
openssl req -text -in myserver.csr -noout -verify
# -in csr 文件路径
使用 csr 和 私钥生成自签证书
openssl x509 \
-sha256 \
-signkey rsa_private_key.pem \
-in myserver.csr \
-req -days 365 -out domain3.crt
# x509 生成 x509 格式的证书
# -sha256 证书采用的哈希算法
# -signkey 私钥路径
# -in csr 文件路径
# -days 证书有效天数
# -out 生成的证书路径
一条命令生成密钥和证书
openssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt
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"
查看证书内容
openssl x509 -in domain.crt -noout -text
查看证书序列号
openssl x509 -in domain.crt -noout -serial
查看证书有效时间
openssl x509 -in domain.crt -noout -dates
一般使用 OpenSSL 生成证书时都是 v1 版的,不带扩展属性。 多域名证书需要用到 v3 版的 extensions 的 Subject Alternative Name (SAN 主题替代名称)
寻找默认配置文件
find / -name openssl.cnf
复制一份默认配置文件
cp /usr/ssl/openssl.cnf openssl.cnf
编辑 openssl.cnf
[ alt_names ]
DNS.1 = 3.example.com
DNS.2 = 4.example.com
新建私钥
openssl genrsa -out rsa_private_key.pem 4096
生成 csr 文件
openssl req -new \
-key rsa_private_key.pem \
-keyform PEM \
-config openssl.cnf \
-out myserver.csr
生成数字证书
openssl x509 \
-sha256 \
-signkey rsa_private_key.pem \
-in myserver2.csr \
-extensions v3_req \
-extfile openssl.cnf \
-req -days 365 -out domain.crt
创建 CA 目录
mkdir -p ~/ssl/demoCA/{certs,newcerts,crl,private}
cd ~/ssl/demoCA
Touch index.txt
echo "01" > serial
寻找默认配置文件
find / -name openssl.cnf
复制一份默认配置文件
cp /usr/ssl/openssl.cnf ~/ssl/openssl.cnf
修改 openssl.cnf 文件
[ CA_default ]
dir = /root/ssl/demoCA # Where everything is kept
生成 CA 根证书及密钥
openssl req -new -x509 -newkey rsa:4096 -nodes -keyout cakey.key -out cacert.crt -config openssl.cnf -days 365
生成客户端私钥
openssl genrsa -out client.key 4096
用该客户端私钥生成证书签名请求
openssl req -new -key client.key -out client.csr -config openssl.cnf
使用 CA 根证书签发客户端证书
openssl ca -in client.csr -out client.crt -cert cacert.crt -keyfile cakey.key -config openssl.cnf
policy = policy_anything
一些情况下,从 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 服务端
# 测试 example.com 的 80 端口是否有开启
openssl s_client -connect example.com:80
# 输入这个命令后,会进入一个命令行交互界面,这时快速地输入 GET / HTTP/1.0 然后连续输入两个回车,就能返回网页内容
# -showcerts 在输出中显示服务器证书链的所有证书,而不仅仅是最后一个证书
openssl s_client -connect www.baidu.com:443 -showcerts
openssl smime 用于处理S/MIME邮件,它能加密、解密、签名和验证S/MIME消息
openssl ca ca命令是一个小型CA系统。它能签发证书请求和生成CRL。它维护一个已签发证书状态的文本数据库。
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 的配置文件一般在这里 /etc/ssh/sshd_config
大部分情况下系统都会默认开启 sshd 服务,默认的端口号 22 ,默认监听 ip 0.0.0.0
可用通过像这样的命令 ps -elf | grep sshd
判断 sshd 服务有没有开启
可以直接执行 sshd 的可执行文件来启用 sshd 服务(需要是绝对路径)。 大部分情况下 sshd 的可执行文件是这个路径 /usr/bin/sshd
。
如果运行 usr/bin/sshd
遇到这种错误 sshd: no hostkeys available -- exiting
,那么可以先运行这句 ssh-keygen -A
如果要关闭 sshd 可以先通过 ps -elf
找到对应的 pid ,然后 kill pid
ssh 的配置文件一般在这里
ssh 连接的配置一般在 ~/.ssh
ssh 用密码连接
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=30 -o TCPKeepAlive=yes 用户名@远程地址
# -o ServerAliveInterval 的意思是每 60 秒发送一次请求,用于保持连接的,不加这个参数也可以,但连接很容易就断开了
# -o TCPKeepAlive=yes 表示 TCP 保持连接不断开
# -o ServerAliveCountMax 表示连续 30 次服务端没有响应后,客户端就自动退出,如果有监控进程这类的,可以执行重新连接这类操作
如果需要用密钥连接,就在连接命令里加上 -i 参数
ssh -o ServerAliveInterval=60 -i 密钥路径 用户名@远程地址
ssh 除了登录服务器,还有一大用途,就是作为加密通信的中介, 充当两台服务器之间的通信加密跳板, 使得原本不加密的通信变成加密通信。 这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。
ssh 的端口转发有三种
# 建立隧道
ssh -o ServerAliveInterval=60 -f -N -g -L 127.0.0.1:本地端口:MySQL地址:MySQL端口 用户名@远程地址
# -L 是建立转发 把本地的 9912端口转发到目标服务器地址的3306端口
# -N 不打开新的终端,连接只进行端口转发
# -f 后台运行
# -g 不清楚有什么用?允许远程主机连接到本地转发端口。如果在多路复用连接上使用,则必须在主进程上指定此选项。
# 通常 N f 会配合一起使用
# mysql 连接
mysql -h 127.0.0.1 -uMySQL用户名 --port=本地端口
ssh -o ServerAliveInterval=60 -f -N -g -R 127.0.0.1:远程端口:localhost:9003 用户名@远程地址
GatewayPorts yes
ssh -o ServerAliveInterval=60 -f -N -C -D 6080 用户名@远程地址
# -D 端口上的动态端口转发
# -C 压缩数据传输
# 本地其它程序可以通过类似这样的 url 连接 socks5://127.0.0.1:6080
<!-- ssh 能保证数据的安全性,但 ssh 协议特征是很明显的, --> ssh -L 127.0.0.1:本地端口:代理地址:代理端口
ssh -R 127.0.0.1:远程端口:代理地址:代理端口
ssh 文档 https://man.openbsd.org/ssh
https://wangdoc.com/ssh/port-forwarding
sftp 连接服务器
sftp -o ServerAliveInterval=60 用户名@远程地址
sftp -o ServerAliveInterval=60 -i 密钥路径 用户名@远程地址
sftp 命令参考
# 上传文件
put 本地路径 远程路径
# 下载文件
get 路径路径 本地路径
# 查看服务器路径[默认用户根目录]
pwd
# 列出当前服务器路径下的文件
ls -al
# 更改服务器路径,就是普通的 cd 命令
cd
# 在服务器里新建文件夹
mkdir 文件夹名
# 删除服务器的文件
rm 文件名
# 删除服务器的文件夹
rm -r 文件夹名
# 查看本地路径
lpwd
# 列出本地路径下的文件
lls
# 更改本地路径,和 cd 一样只是前面多了个 l
lcd
# 在本地新建文件夹
lmkdir 文件夹名
# 执行其它本地命令,这里要注意本地的命令行环境
!本地命令
OpenSSH 是 SSH 协议的实现,实现过程中,需要用到密钥交换算法,对称/非对称加密算法,随机数算法,等密码学相关的算法。 早期版本的 OpenSSH 是通过调用 OpenSSL 的库来实现这些算法的。 2014年4月的心脏出血漏洞事件之后, OpenBSD 项目成员以 OpenSSL 1.0.1g 作为分支,创建一个名为 LibreSSL 的项目。 OpenSSH 会逐渐减少对 OpenSSL 的依赖。
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 运行的
查看帮助
gpg --help
新建密钥
gpg --gen-key
# 这里会要求输入用户名和邮箱,用户名和邮箱组合起来就是要用户ID了
# 例如 用户名是 username ,邮箱是 email@123.com ,那么用户ID 就是 username <email@123.com> ,还有就是在命令行里输入时要记得加上双引号
列出系统中已有的密钥
gpg --list-keys
导出公钥
gpg --armor --output public-key.txt --export [用户ID]
导出私钥 需要输入密码
gpg --armor --output private-key.txt --export-secret-keys [用户ID]
导入密钥,可以是公钥也可是私钥
gpg --import [密钥文件]
加密
gpg --armor --recipient [用户ID] --output demo.en.txt --encrypt demo.txt
解密
gpg --recipient [用户ID] --output demo.de.txt --decrypt demo.en.txt
签名
gpg --armor --local-user [用户ID] --output demo.txt.sig --detach-sign demo.txt
验证签名
gpg --armor --recipient [用户ID] --output demo.txt.sig --verify demo.txt
签名 + 加密
gpg --armor --local-user [发信者ID] --recipient [接收者ID] -output demo.txt.asc --sign --encrypt demo.txt
# 直接解密即可,解密的同时会验证签名
gpg --recipient [接收者ID] --output demo.de.txt --decrypt demo.txt.asc
常用的命令参数解释
很多邮件客户端都支持使用 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://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 开源,但似乎不能免费地商用 分组密码 初始化向量(IV,Initialization Vector) 填充(padding) 模式(modes) 伽罗瓦/计数器模式(GCM, Galois/Counter Mode) 电子密码本(ECB, Electronic codebook) 密码块链接(CBC, Cipher-block chaining) 填充密码块链接(PCBC, ) 填充密码块链接(PCBC,Propagating cipher-block chaining)或称为明文密码块链接(Plaintext cipher-block chaining) 密文反馈(CFB, Cipher feedback) 输出反馈(OFB, Output feedback) 计数器模式(CTR, ) CTR模式(Counter mode,CM)也被称为ICM模式(Integer Counter Mode,整数计数模式)和SIC模式(Segmented Integer Counter) -->