1 Star 0 Fork 11

coder_lw / wiki

forked from deepinwiki / wiki 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
linux加密解密.md 31.19 KB
一键复制 编辑 原始数据 按行查看 历史
htqx 提交于 2023-02-23 14:23 . ssh ed25519的支持说明

[TOC]

linux 加密解密

前言

[linux内核编译] 众所周知,我们这个世界上充满偷看隐私的罪恶。不过,linux用户有福气了,因为有一组很方便的工具,可以帮助你加密和解密文档。

2021/11 更新: 最近 openssh 升级,宣布即将弃用 rsa 算法,因此补充使用 ed25519 系列算法生成 gpg 密钥和 Openssh 密钥的内容。

非对称加密

非对称会产生两条钥匙,一条可以公开给别人,另一条自己藏好。别人用公钥加密信息,只有你的私钥才能解密。同样的,你私钥加密的信息,也只有公钥可以解密。

这好像挺对称的,非对称的意思指加密解密用的不是同一根钥匙。这究竟是怎么做到的?这里就不展开讨论了,毕竟密码学是挺复杂的东西。

一般来说,当你想发布可信信息,那么用私钥加密,对方用公钥能解密,说明这个信息是你发布的。这一过程主要目的是验证发布者的身份。

当你想获取信息,别人用公钥加密,只有你能解密查看信息,保证信息的安全性。这一过程叫加密,目的就是为了信息本身。

可见这两个过程目的性是不一样的,一个是确认身份,一个是为了数据保密,分别称为:签名和加密。如果你想将保密数据发给对方,那该怎么办?这时候靠的就不是你这对密钥,而是要得到对方的公钥,用他的公钥加密信息发给他。

你也许注意到这样做最根本的原因在于公钥是公开的,谁都能拿得到。而私钥只有本人才有一份。理解这一过程,就能灵活运用非对称加密技术了。

这套技术,唯一的缺陷,是怎么证明公钥是对方的,而不是第三方伪装的。只要能保证公钥是对方的,那么之间的加密就是完美的,因为还没有听说有什么能破解这套加密体系的新闻。

基本概念

  1. 公钥 :密钥对中公开的钥匙,所有人都可以拥有,即私钥加密的信息是非保密的(所以私钥加密是没意义的,别人能用公开的公钥解密),但私钥加密身份是明确,可以确定当这段加密信息能用公钥解密时,加密方必然是私钥的拥有者。所以私钥的加密行为称为签名,而不是加密(没有保密性)。总结:私钥用来签名和解密,公钥用来加密。
  2. 私钥:密钥对中保密的钥匙。只有私钥主人拥有。即公钥加密的信息是保密的,但身份不确定,任何人都可以发加密信息给私钥的主人。
  3. 签名:私钥对一段信息进行加密,这个操作就能(让公钥持有者)确定加密者身份,这就是所谓签名。但实际操作中为了提高加密效率,并不对所有数据进行加密,而先对数据进行散列(哈希),再对散列值进行加密。
  4. 密钥环: 保存秘钥的机制,类比钥匙扣
  5. 加密算法 : 根据一组密码信息(指导信息)将数据变换成一种不可识别的信息组织,并可恢复原值(解密)的一种算法。
  6. 哈希算法: 将任意长度数据演算出固定长度的字符串,并尽可能保证字符串唯一性的一种算法。常用于数据的签名(意思是可代表数据实体的一个短语,类似人名)
  7. 证书:为了安全交换秘钥的第三方协调者所签出的证明文件。
  8. 密码短语: Passphrase,为了进一步保护私钥文件而设的密码,每次使用私钥都会提示输入密码,推荐 AES 算法。
  9. 指纹: 对密钥文件演算出一段简短但能标识密钥的字符串。

当我们拥有对方的公钥时,自然可以安全的发加密信息给对方,但是难点在于我们怎么安全的获得对方的公钥,而不是第三方伪造的。

PKI(公钥基础结构)引入证书的概念。

  1. CA : 证书颁发机构
  2. Intermediate CA : 中级CA,顶级CA的下属机构
  3. CRL : 证书吊销列表(过时)
  4. OCSP : 在线证书状态协议
  5. RA : 证书注册机构,CA的前端,验证注册用户真实身份
  6. X.509 : 当前的国际标准
    1. 版本号
    2. 序列号
    3. 签名算法
    4. 颁发者信息
    5. 有效期
    6. 被签发主体信息
    7. 主体公钥
    8. 签名
  7. CSR: 证书签名请求(certificate signing request),是一种文件,他保存了证书主体(即私钥拥有者)向 CA 请求证书签名的相关信息。

内容从技术角度来看,证书主要携带被签名主体的公钥,和签名。这个签名是CA的私钥加密然和用签名算法取得散列值得来的。这就保证了该证书是由CA签发,并保证不被第三方所修改。只要你相信CA,那么证书携带的相对方的公钥,必然是没经过修改的。当然,前提你必须先拥有正确的CA公钥,来验证证书自身的正确性。

可见,证书并不解决问题,只是压缩了问题,因为它一样是采用非对称加密技术,只是作为一个管理中枢,来集中管理秘钥的可信任问题。如果你能信任CA,那你就可以信任CA签署的任意证书,即通过解决CA的自身的可信问题,同时解决了数量庞大的关联秘钥信任问题。

SSL(安全套接字层)(过时)和TLS(传输层安全)是常见的使用证书的具体网络协议,HTTPS 安全链接基于此协议来保证网站通信的安全性。

工具包:

  1. openssl : 携带制作证书的工具
  2. openssh : 支持 ssh 隧道,实际部分利用了 openssl 相关加密解密组件
  3. GPG : linux 中支持 PGP 规范的工具

openssh

ssh工具可以登录远程服务器,除了密码登录,还可以支持用公钥私钥技术来自动登录。

默认位置:

  1. ~/.ssh/id_rsa : 私钥
  2. ~/.ssh/id_rsa.pub : 公钥

支持的格式:

  1. SSH2 / RFC4716格式 (默认输出)
    1. 私钥抬头: (工具不产生)
    2. 公钥抬头:BEGIN SSH2 PUBLIC KEY
  2. PKCS8 : 证书
    1. 私钥抬头:BEGIN PRIVATE KEY
    2. 公钥抬头:BEGIN PUBLIC KEY
  3. PEM / pkcs1: 实际是 pkcs1
    1. 私钥抬头:BEGIN RSA PRIVATE KEY
    2. 公钥抬头:BEGIN RSA PUBLIC KEY
  4. openssh:默认私钥
    1. 私钥抬头:BEGIN OPENSSH PRIVATE KEY
    2. 公钥:ssh-rsa .... htqx@xxx.com

ssh-keygen 对密钥文件的操作逻辑有点怪异。它将转换任务设计成非常奇怪的数个命令。

ssh-keygen 工具的基本逻辑:

  1. -i : 读取外部格式,输出内部格式
  2. -e : 读取内部格式密钥,输出外部格式公钥
  3. -p : 设置密码(空为转换格式),将内部格式私钥转换成外部格式
  4. -y : 输出对应私钥的公钥(内部格式)
  5. -m : 指定输入输出的格式: pem / pkcs8 / ssh2
# 注意:私钥实际上是可以输出公钥的
# 也就是私钥本身包含公钥信息,而公钥只含公钥信息
# openssh 私钥 -> openssh 公钥
ssh-keygen -f xxx.key > xxx.pub

# openssh 私钥 -> 其他格式(原地转换)
ssh-keygen -f xxx.key -pN '' -m pem
# ed25519 密钥暂时还没支持
# 需要安装转换工具
sudo npm install -g sshpk
sshpk-conv -f xxx.key -p -t pem > xxx.pem

# 其他格式私钥 -> openssh 私钥(原地转换)
ssh-keygen -f xxx.pem -pN ''

# openssh -> 其他格式公钥(注意有些加密算法只有 ssh2 支持)
ssh-keygen -f xxx.key -em pem > xxx.pub.pem
# 其他格式 -> openssh
ssh-keygen -f xxx.pem -im pem > xxx.key
ssh-keygen -f xxx.pub -im pem > xxx.pub.pem

openssl 使用的公钥格式是 pkcs 8 的:

  1. 公钥抬头:BEGIN PUBLIC KEY
  2. 转换这两种格式的公钥:
    1. 私钥 --> pkcs8 : openssl rsa -in htqx.key -out htqx.pem
    2. pem --> pkcs8 : openssl rsa -RSAPublicKey_in -in htqx.pub -out htqx.pem
    3. pkcs8 --> pem : openssl rsa -RSAPublicKey_out -in htqx.pem -out htqx.pub

私钥支持添加密码保护。

常用命令组合:

  1. ssh-keygen -b 2048 -C "htqx@xxx.com" -m pem -f htqx.key : 创建 pem 格式 2048 位私钥,注释标记 “htqx@xxx.com",私钥文件名 htqx.key ,公钥文件是 htqx.key.pub ,格式是 RFC4716 的。
  2. ssh-keygen -e -f htqx.key -m pem > htqx.pem : 输出 pem 格式公钥
  3. 私钥格式转换
    1. pem --> openssh : ssh-keygen -p -N '' -f htqx.key
    2. openssh --> pem : ssh-keygen -p -N '' -m pem -f htqx.key
  4. 查看指纹:ssh-keygen -lf htqx.key
# 创建秘钥对
# -t 选择算法
# -b 长度
# -C 标识
# 接下来提示输入私钥文件名
# 如 xxx 产生 xxx(私钥)/xxx.pub(公钥)
# 然后输入该文件本身的密码,可以省略
ssh-keygen -t rsa -b 4096 -C "htqx@xxx.com"

ssh的管理目录在用户目录下 ~/.ssh/

  1. authorized_keys : 可登录本机的公钥,即只要把公钥写入服务器这个文件即可
  2. config : 配置文件
  3. xxx/xxx.pub : 一般秘钥存放在此
  4. known_hosts: 登录过的服务器识别信息
# 打印公钥的指纹信息
# 指纹信息可以帮助用户快速对比秘钥信息
ssh-keygen -E md5 -lf xxx.pub

# 私钥托管到代理工具ssh-agent
ssh-add xxx

# 产生证书
# 产生CA自身的秘钥对
ssh-keygen -f htqx_ca
# 用户秘钥对
ssh-keygen -f htqx -C "htqx@xxx.com"
# 签署证书
# 产生 htqx-cert.pub 文件
ssh-keygen -s htqx_ca -I myid htqx.pub

命令摘要

ssh-keygen: 生成、管理、转换秘钥文件。

  1. -b : 位数
  2. -C : 标识备注
  3. -e : 读取openssh 兼容秘钥,产生 RFC4716 格式(或-m 指定)公钥
  4. -F : 搜索 known_hosts 主机
  5. -f : 秘钥文件
  6. -i : 读取 RFC4716 格式(或-m 指定),标准输出 openssh 兼容公钥
  7. -N : 新密码
  8. -p : 修改密码
  9. -t : 秘钥算法类型:rsa / dsa / ed25519 / ecdsa
  10. -y : 读取 openssh 兼容秘钥,输出公共秘钥
  11. -D : PKCS 11 托管令牌(密钥设备)
  12. -E : 哈希算法 sha256 / md5
  13. -m : 格式 RFC4716 / PKCS8 / PEM
  14. -l : 公钥指纹
  15. -I : 证书标识
  16. -s : 证书 CA 秘钥
  17. -h : 主机证书(默认用户证书)
  18. -U : 托管 ssh-agent
  19. -n : 有效主体(用户或者主机)

连接 gitee 失败

补充一个案例,最近(2021年11月),我发现连接 gitee 失败,之前是可以的。估计是系统的一个 bug,解决方案是修改 ~/.ssh/config

Host gitee.com
    HostName gitee.com
    User git 
    PubkeyAcceptedKeyTypes=+ssh-rsa # 增加这行
    IdentityFile ~/.ssh/htqxgit_rsa # 俺的私钥

测试连接:

ssh -Tv gitee.com
# ...
# Hi htqx! You've successfully authenticated, but GITEE.COM does not provide shell access

openssl

openssl是一个很底层的强大密码学工具。一般会用他来创建证书。

openssl 支持格式

  1. openssl help : 查看算法和功能菜单
  2. 散列算法: md5,sha1,sha256,sha512,sm3...
  3. 加密算法: sm4-cbc,des,des3,idea,zlib...
  4. 菜单:
    1. ca
    2. pkcs8
    3. pkcs12
    4. x509
    5. rsa
    6. genrsa
    7. rsautl
    8. req
    9. pkeyutl
    10. 等等

常用命令组合

  1. 密码加密解密
    1. 加密:openssl 加密算法 -in 原文件 -out 输出文件
      1. -e :加密
      2. -d :解密
      3. -a : 文本格式
      4. -k : 密码
      5. -kfile : 密码文件
      6. -z : 压缩
    2. 解密:openssl 加密算法 -d -in 加密文件 -out 输出文件
  2. 求散列值:
    1. openssl 散列算法 文件
      1. -sign : 用私钥签名
      2. -prverify : 用私钥验证签名文件
      3. -verify : 用公钥验证签名文件
      4. -signature :签名文件
  3. 公钥私钥加密解密:
    1. openssl pkeyutl -in 不大于116字节的文件 -out 输出 -encrypt -inkey 私钥
      1. -encrypt : 加密
      2. -decrypt : 解密
      3. -inkey : 私钥
  4. 签名:
    1. openssl rsautl -sign -inkey 私钥 -in 原文件散列 -out 签名
    2. 验证: openssl rsautl -verify -inkey 公钥 -pubin -in 签名
  5. 证书签名请求:
    1. openssl req -new -key 私钥 -nodes -out 证书请求.csr
    2. openssl req -newkey rsa:2048 -nodes -keyout 新私钥 -out 证书请求.csr
    3. openssl req -new -key 私钥 -config 配置文件 -out 证书请求.csr
  6. 证书:
    1. openssl x509 -req -in 证书请求.csr -signkey 私钥 -out 证书.crt -days 3650 -extfile v3.ext
      1. -req :输入文件是一个证书请求
      2. -in : 输入
      3. -out : 输出
      4. -signkey: 签署所用的私钥
      5. -days : 有效期 10 年
      6. -config : 配置文件(写法在下面介绍)
      7. -extfile : v3 证书的扩展配置
    2. openssl req -x509 -key 私钥 -config 配置文件 -out 证书请求.csr
      1. 一条命令生成自签名证书 (不指定有效期为一个月)
    3. 验证证书:openssl verify -CAfile 签署私钥自身的证书 私钥所签署的证书

创建证书步骤

  1. 创建私钥(准确的说是密钥对,它可以导出公钥)
  2. 创建证书请求文件.csr
  3. 通过CA来签署(第三方或者自己创建一个自签名的CA,但此CA没有公信力)

证书请求文件配置

可以通过交互式提供证书请求文件需要的信息,也可以通过配置文件来批量生产证书请求文件。

信息:

  1. 国家简称(C)
  2. 省份(ST)
  3. 城市(L)
  4. 公司(O)
  5. 组织(OU)
  6. 域名或个人名称(CN)
  7. 邮箱(emailAddress)

请求配置文件(自动填写以上内容) csr.cnf:

[ req ]
encrypt_key = no
distinguished_name = dn
prompt = no

[ dn ]
C = CN
O = ktongsoft
CN = htqx
emailAddress = htqx@xxx.com

注意: x509 证书有两个版本,v1 和 v3, 默认是 v1 的,如果要签署 v3 证书,需要提供 v3 的扩展配置.

v3.ext:

subjectAltName = DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer

例子:

# 创建 25519 私钥
openssl genpkey -algorithm ED25519 > htqx3.key

# 请求证书
openssl req -new -out htqx3.csr -key htqx3.key -config htqx3.csr.cnf 

# 签署 v3 版证书
openssl x509 -req -days 100 -in htqx3.csr -signkey htqx3.key -out htqx3.crt -extfile htqx3.ext

# 查看证书资料
openssl x509 -in htqx3.crt -text -noout

演示

# 创建私钥
openssl genrsa -out ca.key 4096
# 导出公钥
openssl rsa -in ca.key -pubout -out ca.pub 

# 创建x509证书(自签名)
openssl req -new -x509 -days 365 -key ca.key -out ca.crt 

# 给其他公钥签署证书
# 创建用户秘钥
openssl genrsa -out htqx.key 4096 
# 用秘钥生成证书请求文件
openssl req -new -key htqx.key -out htqx.csr 
# 用ca自签名证书和ca秘钥来签署证书请求文件,生成用户证书
openssl x509 -days 3 -CA ca.crt -CAkey ca.key -CAcreateserial -req -in htqx.csr -out htqx.crt

GPG

GPG是一个基于非对称加密技术的工具。开源世界很多地方实际使用的是这个工具。

它的优点:

  1. 命令简单(相对openssl)
  2. 对任意大小文件的加密,签名
  3. 支持身份验证

一、安装

  1. sudo apt install gnupg

二、密钥对管理

  1. gpg --gen-key 生成密钥对,对话式。一般过程是要求你输入名字ID,邮箱,然后让你随意输入一大堆产生随机密钥的信息,随便打一大段就行了,过一段比较长的时间,它就会产生密钥对。还有可能让你输入私钥的访问密码。
  2. gpg --gen-revoke ID 根据名称id生成报废密钥对的一个证书,这个证书可以给第三方验证密钥有效性的机构使用。
  3. gpg --list-keys 列出系统有的密钥
  4. gpg --delete-key ID 删除指定id公钥
  5. gpg --delete-secret-keys ID 删除私钥
  6. gpg --output id.pub --export ID 输出指定ID的公钥文件,文件名:id.pub
  7. gpg --output id.key --export-secret-keys ID 输出私钥。
  8. gpg --fingerprint ID 根据id输出公钥的指纹信息。可以公布这个信息让持有公钥的人确认公钥是你的。
  9. gpg --send-keys ID --keyserver xxx上传到第三方公钥存放服务器
  10. gpg --import 密钥文件 系统添加以文件存储的密钥
  11. gpg --keyserver xxx --search-keys ID 在第三方公钥存放服务器查找密钥

三、签名和解密

记住:用自己的密钥对,能做的是签名和解密,所以放在这一节描述。

  1. gpg --decrypt file.gpg 解密别人用你的公钥发给你的加密文件file.gpg
  2. gpg --armor --detach-sign --output file.asc file 用私钥签名file文件,输出独立的签名文件file.asc,
    1. --armor表示输出文本而非二进制,
    2. --detach-sign表示分离式签名,不合并原文件内容,这套参数我认为是比较合理的,因为签名往往需要在网站等场合公布出来,让别人验证。

四、验证和加密

用别人的密钥对,能做的是验证对方身份,和加密信息发给对方。

  1. gpg --recipient 对方ID --output file.gpg --encrypt file 首先你得安装对方公钥,得到对方id,然后加密file文件输出为file.gpg,这个文件就可以公开发送给对方,不需要担心别人截获该文件,因为只有对方用他的私钥才能解密。
  2. gpg --verify file.asc file 通过签名文件和原文件,可以验证签名,即文件没有被修改过,确实由密钥对持有者发出的原始文件。这个签名文件,对方可以在网站上贴出内容,因为是文本的。你只需要复制下来保存文件即可。

当然,从技术上讲,你也可以加密发给自己。

五、命令参数

单字添加前缀-,多字添加前缀

  1. s、sign 签名
  2. clear-sing 文本签名
  3. b、detach-sign 独立签名
  4. e、encrypt 加密
  5. c、symmetric 对称加密
  6. d、decrypt(默认参数)解密
  7. verify 验证签名
  8. k、list-keys 列出公钥
  9. list-signatures 列出公钥和签名
  10. check-signatures 列出并检查公钥签名
  11. fingerprint 公钥指纹
  12. K、list-secret-keys 列出私钥
  13. genetate-key 生成密钥对
  14. quick-generate-key 快速生成密钥对
  15. quick-add-uid 快速添加新用户ID
  16. quick-revoke-uid 快速撤销用户ID
  17. quick-set-expire 快速设置新的到期日期
  18. full-generate-key 全功能生成密钥对
  19. generate-revocation 生成撤销证书
  20. delete-keys 删除公钥
  21. delete-secret-keys 删除私钥
  22. quick-sign-key 快速签名密钥
  23. quick-lsign-key 快速签名本地密钥
  24. quick-sign-key
  25. sign-key 签名密钥
  26. lsign-key 签名本地密钥
  27. edit-key 签名或编辑密钥
  28. change-passphrase 改变密钥使用密码
  29. export 导出公钥
  30. send-keys 上传公钥
  31. receive-keys 下载并导入公钥
  32. search-keys 搜索公钥
  33. refresh-keys 更新公钥
  34. import 导入密钥
  35. card-status 打印卡状态
  36. edit-card 编辑卡
  37. change-pin 更改卡pin码
  38. update-trustdb 更新信任数据库
  39. print-md 打印消息摘要
  40. server 以服务器模式运行
  41. tofu-policy 实施TOFU策略

选项:

  1. a、armor 输出文本
  2. r、recipient 加密ID
  3. u、local-user 签名、解密ID
  4. z 压缩级别
  5. textmode 规范文本模式
  6. o、output 输出文件
  7. v、verbose 详细信息
  8. n、dry-run 不做任何更改
  9. i、interactive 交互式
  10. openpgp 严格模式

六、子密钥

公钥私钥的保管是个问题,如果泄露了私钥,你可以声明撤销证书,但曾经签署的文件也都一同失效了。

为此,GPG 提出了子密钥(sub key)的概念。

pgp 密钥的能力:

  1. S:签名
  2. E:加密
  3. A:身份验证
  4. C:验证其他密钥 (主密钥)

主密钥和子密钥是类似的,但主密钥可以管理 S E A 类型的子密钥。

可以先创建好子密钥后,然后把主密钥移走,这样密钥也是可以工作的。这个有点类似 x509 的 ca 证书。

标识:

  1. sec: 主密钥
    1. ssb: 子密钥
  2. uid: 用户id
  3. pub: 公钥
    1. sub: 对应的子公钥
gpg --edit-key 用户
# 进入管理界面,用addkey 添加子密钥

创建 ed25519 新密钥的案例

首先是用 gpg 创建 SC 主密钥,然后创建导出给 openssl 的 A 子密钥,同时创建子密钥 E,和子密钥 S 备用。

创建主密钥的吊销证书备份。

保存私钥和公钥到文件备份。

第二步:

gpg 密钥环中删除 gpg 主密钥,保留子密钥。从而保护了主密钥。

第三步:

本来想从 gpg 导出给 openssh 使用的,但是,gpg 交互性不是很好,默认支持的是 rsa 算法,对 ed25519 的导出不支持。所以得独立生成 openssh 的密钥对。

另一个方案是 openssh 通过代理给 gpg 来管理密钥,从而使用 gpg 的 ed25519 密钥,方法:https://blog.mozcp.com/use-gnupg-agent-as-ssh-agent

# ed25519 密钥需要添加 expert 参数才有
# 选择 10 ECC(sign only)
# 选择 1 curve 25519 算法
# 选择证书的有效期,随你
# 输入识别id / email / 备注
# 最后需要提供一个稍微复杂的密码(大小写数字等)
gpg --expert --full-gen-key

# 密码是交互式的,如果想关闭密码提示,需要添加 --batch 批处理模式,但是这时候需要你提供所有的参数
# 类似下面的写法: passphrase 是密码, 最后是 id / 算法 / 用途 / 有效期
gpg --batch --expert --passphrase '' --quick-gen-key 'ktong (main) <htqx@xxx.com>' ed25519 sign none

# 列出私钥信息,如
# sec   ed25519/16D4D7AA 2021-11-09 [SC]
# uid           [ 绝对 ] ktong (gpg main key) <htqx@xxx.com>
# sec 表示密钥类型
# ed25519 算法
# 16d4d7aa 是密钥的短8位 id
# uid 是用户 id 
# [绝对] 是系统对该密钥的信任程度
# --with-keygrip 列出在密钥环中的位置,这是 gpg 中唯一标识一个密钥对的方式
# --keyid-format 列出 id 的格式,short 是8位id,该 id 可用于命令上下文
# -K 私钥
# -k 公钥
gpg -K --keyid-format short

# 添加子密钥,进入交互模式
# help 显示可用命令
# quit 退出交互模式
gpg --expert --edit-key 16D4D7AA

# 添加子密钥,过程类似创建主密钥
# 选择的算法是 ECC(set your own capabilities) ,简而言之就是控制子密钥的用户,S 是签名, A 是身份认证
# ECC(encrypt only) 是 E 加密
addkey

save # 保存退出

# 这步完成之后,密钥信息应该类似:
sec   ed25519/16D4D7AA 2021-11-09 [SC]
      5438FE62374A7EBD32599F3E0DDF6E7C16D4D7AA
uid           [ 绝对 ] ktong (gpg main key) <htqx@xxx.com>
ssb   ed25519/05F7DEE4 2021-11-09 [A]
ssb   ed25519/EFDBAE91 2021-11-09 [S]
ssb   cv25519/3A3CB025 2021-11-09 [E]

# 接下来保存密钥对和吊销证书。主密钥可以吊销子密钥,吊销证书可以吊销主密钥,大概就是这么的关系
# 吊销证书
gpg -o ktong.sc.revoke --gen-revoke 16D4D7AA
# 私钥
gpg -o ktong.sc.key --export-secret-keys --armor 16D4D7AA
# 子密钥
gpg -o ktong.sc.sub --export-secret-subkeys --armor 16D4D7AA
# 公钥
gpg -o ktong.sc.pub --export-keys --armor 16D4D7AA

# 删除主密钥(连同子密钥一起删除)
gpg --delete-secret-key 16D4D7AA
# 重新导入子密钥
gpg --import ktong.sc.sub  

# sec#  ed25519/16D4D7AA 2021-11-09 [SC]
#       5438FE62374A7EBD32599F3E0DDF6E7C16D4D7AA
# uid           [ 绝对 ] ktong (gpg main key) <htqx@qq.com>
# ssb   ed25519/05F7DEE4 2021-11-09 [A]
# ssb   ed25519/EFDBAE91 2021-11-09 [S]
# ssb   cv25519/3A3CB025 2021-11-09 [E]

# sec# 表示主密钥并不在系统中

openssh 生成 ed25519 密钥对:

# 默认生成 id_ed25519 和 id_ed25519.pub 密钥对
ssh-keygen -t ed25519

秘钥文件格式转换

不同的工具,原理上差不多,但是产生的秘钥文件的格式也许是不一样的。如果你想用同一对秘钥,那么就考虑一下转换他们之间的格式。

主要注意,密码系统使用的扩展名非常多,而且意义并不十分明确。同一个东西在不同的角度,可以使用不同的扩展名。

本文约定如下:

编码方式:

  1. PEM : 文本,.pem 后缀
  2. der : 二进制,.der 后缀

用途:

  1. .key : 私钥
  2. .pub : 公钥
  3. .crt :文本证书
  4. .cer : 二进制证书
  5. .csr : 证书请求文件

规范:

  1. .p1 : pkcs 1 规范
  2. .p7b / .p7c : pkcs 7 规范证书(含私钥)、证书
  3. .p8 : pkcs 8 规范
  4. .p12 : pkcs 12 规范证书(含私钥)
  5. .x509 : 最常用的证书格式(可隐含)

常见的秘钥文件格式:

  1. PEM: openssl 通用的秘钥格式,符合X.509标准的Base64编码。
  2. openssh: openssh会产生这个私钥格式(但它也支持PEM)
  3. RFC4716: SSH2 私钥和公钥的文件格式
  4. PKCS8: 私钥机密格式
  5. .pub: ssh 公钥的格式
  6. .ppk: putty 秘钥格式
  7. .pfx: p12 之前的格式,包含公钥和私钥
  8. .der: 符合X.509标准的二进制
  9. .p7b: PKCS#7 格式,加密数据和签名容器。
  10. .p7c: 同上,但不含签名。
  11. .p12 /.pm: PKCS#12 格式。公钥私钥合集。
  12. .key : 私钥 (不明确具体文件格式)
  13. .cer: 证书,一般为二进制格式
  14. .crt: 证书(不明确具体文件格式)一般为文本模式
  15. .csr : 证书请求文件

OPENSSH --> PEM

# 读取标准openssh私钥,输出PEM格式私钥
# 备份原秘钥,因为这个方式是通过修改密码
# 直接在原秘钥上复写的
mv -v xxx{,.bak}
ssh-keygen -m PEM -p -N "" -f xxx
# 反向
ssh-keygen -pN "" -f xxx

# 读取兼容公钥,输出PEM公钥
ssh-keygen -e -m PEM -f xxx.pub > xxx.pem
# 反向
ssh-keygen -i -m PEM -f xxx.pem 
# 通过私钥输出公钥
ssh-keygen -f xxx -y 

.pfx --> PEM

# 从 .pfx 到 pem 证书
openssl pkcs12 -in certificate.pfx -nokey -out certificate.crt
# 从 .pfx 到私钥(加密格式)
openssl pkcs12 -in certificate.pfx -out privatekey.key
# 从 .pfx 到 pem 私钥(rsa)
openssl rsa -in certificate.pfx -out privatekey_rsa.key
# 反向
openssl pkcs12 -export -in certificate.crt -inkey privatekey.key -out certificate.pfx

# 通过私钥导出公钥
openssl rsa -in privatekey_rsa.key -pubout -out publickey_rsa.key
# 通过证书导出公钥
openssl x509 -in certificate.crt -pubkey -out publickey_rsa.key

.der --> PEM

# 从 .der(.cer) 到 pem 证书
openssl x509 -inform der -in certificate.cer -out certificate.pem

# 反向
openssl x509 -outform der -in certificate.pem -out certificate.der

x509 --> gpg

并不能直接转换。但是可以借助一个公共的桥梁,那就是 .p12 格式。gpg 有一个工具可以使用 p12 格式。

如果想要用原版的 gpg ,两种证书是无法沟通的,但是他们都支持 rsa 的密钥,共用同一个 rsa 密钥是可以的,但证书信息得重建。

  1. gpg --> rsa --> openssl
  2. openssl --> rsa --> gpg

gpgsm :

# 将公钥和私钥转换为 p12 格式
openssl pkcs12 --export -in db.crt -inkey db.key -out db.p12

# 导入
# gpgsm 是一个实用工具,它有类似 gpg 的参数形式,所以你可以把它当gpg来用(但有一些细微不同),它能够支持 p12 密钥。
gpgsm --import db.p12

gpg:


# monkeysphere 包
# 转换私钥格式
cat db.key | PEM2OPENPGP_USAGE_FLAGS=authenticate,sign,certify,encrypt pem2openpgp "htqx <htqx@xxx.com>" > db.pgp

# 再导入 gpg
gpg --import db.pgp

逆过程

gpgsm:

# 查看私钥
gpg -K

# 导出 p12
gpgsm -o gpg.p12 --export-secret-key-p12  htqx
# 导出 pem(openssl 最喜欢的格式)
openssl pkcs12 -in gpg.p12 -out gpg.pem -nodes

# 生成 x509 证书
openssl x509 -in gpg.pem -out gpg.crt

# 查看证书信息
openssl x509 -in gpg.crt -text -noout

gpg:

# 导出 $KEYID 是证书的指纹
gpg --export $KEYID | openpgp2pem $KEYID > htqx.pub # 公钥
gpg --export-secret-key $KEYID | openpgp2pem $KEYID > htqx.key # 私钥

案例

本案例将本人的 openssh 密钥,同时用在 openssl 和 gpg 的场合。

现有:

  1. htqxgit_rsa : pkcs 1 格式
  2. htqxgit_rsa.pub : openssh 公钥格式

都是 openssh 的 ssh-keygen 生成的。

# 因为 openssl 支持 pkcs 1(也就是openssh 中的pem 格式) 的私钥
# 所以可以直接用。 
# 不过 openssl 支持的公钥却是 pkcs 8 的。有点意思
# 但是有私钥就能导出公钥,所以并不需要特别的生成 pkcs8 的公钥
# 如果你的 openssh 私钥是 openssh 格式的,可以通过以下方式转换
cp -v htqxgit_rsa htqx.key # 转换是原地,最好备份
ssh-keygen -p -N '' -m pem -f htqx.key

# 证书请求文件
openssl req -new -key htqx.key -config csr.conf -out htqx.csr
# 如果懒得写配置文件(CN 写用途也可以)
openssl req -new -key htqx.key -subj "/CN=htqx/emailAddress=htqx@xxx.com/" -nodes -out htqx.csr

# 签署为正式证书(v3 版证书必须要提供 v3.ext 配置文件)
openssl x509 -req -in htqx.csr -signkey htqx.key -out htqx.crt -days 3650 -extfile v3.ext
openssl x509 -in htqx.crt -out htqx.cer -outform der # 二进制证书

# pgp 证书
# 导入同一个 私钥( x509 和 pgp 证书无法直接转换,只能共用同一个密钥)
cat htqx.key | PEM2OPENPGP_USAGE_FLAGS=authenticate,sign,certify,encrypt pem2openpgp "htqx <htqx@xxx.com>" | gpg --import

gpg -K # 查看刚导进来的密钥,记住指纹信息
gpg --edit-key 0E3A1C4B2F9C3E7842A0905472C5BD4D03B950C1
# 进入管理页面,设置信任,有效期等配置
gpg --export 03B950C1 > htqx.pgp # 导出公钥
gpg --export-secret-keys 03B950C1 > htqx.pgp.key # 导出私钥

系统密钥环

密钥环即保存秘钥的区域,这个不同的密码系统可能保存在不同的地方。

密码:

  1. ~/.local/share/keyrings/
  2. ~/.gnupg/pubring.gpg : GPG
  3. ~/.ssh/ :SSH

根证书:

  1. /usr/share/ca-Certificates/
  2. update-ca-certificates
# 图形管理工具
# 可以管理ssh, 证书, pgp, 密码四个区域
sudo apt install seahorse

参考

  1. GPG入门教程:http://www.ruanyifeng.com/blog/2013/07/gpg.html
  2. SSH-KEYGEN BSD通用命令手册: http://man7.org/linux/man-pages/man1/ssh-keygen.1.html
  3. Openssh Private Key to RSA Private Key: https://stackoverflow.com/questions/54994641/openssh-private-key-to-rsa-private-key
  4. 在openssl和openssh之间转换密钥: https://security.stackexchange.com/questions/32768/converting-keys-between-openssl-and-openssh
  5. OpenSSL –如何将SSL证书转换成各种格式– PEM CRT CER PFX P12等: https://www.ryadel.com/en/openssl-convert-ssl-certificates-pem-crt-cer-pfx-p12-linux-windows/
  6. openssl、x509、crt、cer、key、csr、ssl、tls 这些都是什么鬼?: https://www.cnblogs.com/yjmyzz/p/openssl-tutorial.html
  7. OpenSSL-密钥和证书管理: https://www.cnblogs.com/LubinLew/p/OpenSSL-Cookbook.html
  8. GPG、OPENSSL、OPENSSH 安全入门:https://www.integralist.co.uk/posts/security-basics/
  9. 创建完美的 GPG 密钥对:https://alexcabal.com/creating-the-perfect-gpg-keypair
  10. openssl 食谱:https://www.feistyduck.com/books/openssl-cookbook/
  11. 在 GnuPG、OpenSsh 和 OpenSSL 之间转换密钥:http://sysmic.org/dotclear/index.php?post/2010/03/24/Convert-keys-betweens-GnuPG%2C-OpenSsh-and-OpenSSL
  12. pem2openpgp : http://manpages.ubuntu.com/manpages/xenial/en/man1/pem2openpgp.1.html#:~:text=pem2openpgp%20is%20a%20low-level%20utility%20for%20transforming%20raw%2C,material%2C%20%20so%20they%20should%20be%20handled%20carefully.
  13. OpenSSL入门教程分为6步骤: https://jhrs.com/2020/39063.html
  14. PKCS 15 个标准: https://www.cnblogs.com/jtlgb/p/6762050.html
  15. 使用 GnuPG(OpenPGP) ECC(ed25519/ecc25519) 密钥作为 ssh 登录密钥: https://blog.mozcp.com/use-gnupg-agent-as-ssh-agent/
1
https://gitee.com/coder_lw/wiki.git
git@gitee.com:coder_lw/wiki.git
coder_lw
wiki
wiki
master

搜索帮助