密码学之密钥编码


个人主页


背景

在密码学的应用实践中,不可避免的会涉及到各种密钥文件、数字证书等,这些文件通常以下面形式出现:

  • xyz.key 一般表示存储内容为私钥
  • xyz.pub 一般表示存储内容为公钥(非对称密码体制公私钥对中的公钥)
  • xyz.crt 一般表示存储内容为x.509数字证书
  • xyz.csr 一般表示存储内容为证书请求,用于向CA机构申请数字证书
  • xyz.pem 一般情况下,需要根据文件内容判断存储内容为私钥、公钥或者证书等
  • xyz.p12或xyz.pfx 一般表示存储的内容包含私钥和数字证书,并使用口令进行了保护。

基本概念

  • ASN.1抽象语法表示
    • 通用数据表示语言,用于描述不同类型数据
    • 独立于编程语言的格式
  • DER编码
    • 按照规则将数据编码二进制格式
    • 能够减小数据体积,提高传输效率,保证数据可移植性
  • Base64编码
    • 将二进制数据编码为可打印ASCII字符
    • 可被文本传输协议直接传输,不能加密数据
  • PEM格式
    • 基于Base64编码,用于存储和传输公钥、私钥和证书等信息
    • -----BEGIN-----END开头和结尾

在密码学中,以上编码或格式紧密联系,通常处于数据表示的不同阶段,如下:


常见密钥编码


密码学标准

密码学中常见的关于密钥相关的标准有:

  • PKCS#1: RSA密码学标准,定义了RSA公私钥的格式和属性,以及加解密、签名、填充的基础算法。 私钥支持加密
  • ECC格式:描述了椭圆曲线类型的私钥格式,在rfc5915中定义
  • PKCS#8:一种通用的私钥格式标准,不仅支持RSA,还支持ECC、SM2等各类私钥。包含算法标识和私钥内容。 私钥支持加密
  • PKCS#12:可以存储证书,私钥或者CRL,多用于Java语言
  • PKIX:通用的公钥格式,包含算法标识和公钥内容
  • X.509:数字证书格式标准,包含主体、签发者、公钥、有效期、签名算法、签发者签名信息等,通常用来代表主体的数字身份。

这些标准都属于或包含对密码学密钥该关键数据结构的描述定义,与ASN.1关系如下:


密钥PEM格式

密码学中常见的PEM举例:

  1. PKCS#1对应的PEM格式
# RSA私钥
-----BEGIN RSA PRIVATE KEY-----
[私钥数据]
-----END RSA PRIVATE KEY-----

# RSA公钥
-----BEGIN RSA PUBLIC KEY-----
[公钥数据]
-----END RSA PUBLIC KEY-----
  1. ECC私钥对应的PEM格式
# ec私钥
-----BEGIN EC PRIVATE KEY-----
[私钥数据]
-----END EC PRIVATE KEY-----
  1. PKCS#8和PKIX对应的PEM格式
# PKCS8私钥
-----BEGIN PRIVATE KEY-----
[私钥数据]
-----END PRIVATE KEY-----

# PKIX公钥
-----BEGIN PUBLIC KEY-----
[公钥数据]
-----END PUBLIC KEY-----
  1. X.509对应的PEM格式
# x.509证书
-----BEGIN CERTIFICATE-----
[证书数据]
-----END CERTIFICATE-----

注:PEM格式并不是严格定义的标准,它们可能会存在一些变体和扩展,例如 PKCS#12、PKCS#15等,因此在使用PEM格式的时候需要留意文件内容和文件类型的匹配关系。


举例

下面以PKCS8为例(借住openssl工具)

  1. 生成密钥
# 生成ec密钥
➜ openssl ecparam -name prime256v1 -genkey -noout -out private.ec.key

# 查看密钥(可以看到默认生成的为pem格式的ec密钥)
➜  cat private.ec.key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOxGa7f/l5VeH2H7YtGM63JPCr1XaBszCy++x9/876A9oAoGCCqGSM49
AwEHoUQDQgAENHVn+siN+rURI8h9TSdZj6DZDKq3WXEVkGY40GBSbLxc/u8T4jby
k/i5NKDzN1ZB66QYjoVuJkF2hD6LWckM4w==
-----END EC PRIVATE KEY-----

# 解析密钥(通过ASN1 OID字段,可以看到为prime256v1曲线的ec类密钥)
➜  openssl ec -in private.ec.key -noout -text
read EC key
Private-Key: (256 bit)
priv:
    ec:46:6b:b7:ff:97:95:5e:1f:61:fb:62:d1:8c:eb:
    72:4f:0a:bd:57:68:1b:33:0b:2f:be:c7:df:fc:ef:
    a0:3d
pub:
    04:34:75:67:fa:c8:8d:fa:b5:11:23:c8:7d:4d:27:
    59:8f:a0:d9:0c:aa:b7:59:71:15:90:66:38:d0:60:
    52:6c:bc:5c:fe:ef:13:e2:36:f2:93:f8:b9:34:a0:
    f3:37:56:41:eb:a4:18:8e:85:6e:26:41:76:84:3e:
    8b:59:c9:0c:e3
ASN1 OID: prime256v1
NIST CURVE: P-256
  1. 查看ec密钥的ASN.1表示
➜  openssl asn1parse -in private.ec.key
    0:d=0  hl=2 l= 119 cons: SEQUENCE
    2:d=1  hl=2 l=   1 prim: INTEGER           :01
    5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:EC466BB7FF97955E1F61FB62D18CEB724F0ABD57681B330B2FBEC7DFFCEFA03D # ecc私钥
   39:d=1  hl=2 l=  10 cons: cont [ 0 ]
   41:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1 #ecc算法曲线
   51:d=1  hl=2 l=  68 cons: cont [ 1 ]
   53:d=2  hl=2 l=  66 prim: BIT STRING
   
# 注:ec标准与pkcs#1类似,仅用于描述ec类密钥
  1. 将ec密钥转换为pkcs8格式,并查看对应ASN.1表示
# 将ec格式密钥转换为pkcs8格式(这里使用nocrypt参数表示不加密)
➜  openssl pkcs8 -in private.ec.key -topk8 -out private.p8.key -nocrypt

# 查看pem格式的pkcs8密钥
➜  cat private.p8.key
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7EZrt/+XlV4fYfti
0Yzrck8KvVdoGzMLL77H3/zvoD2hRANCAAQ0dWf6yI36tREjyH1NJ1mPoNkMqrdZ
cRWQZjjQYFJsvFz+7xPiNvKT+Lk0oPM3VkHrpBiOhW4mQXaEPotZyQzj
-----END PRIVATE KEY-----

# 查看pkcs8密钥的asn.1表示
➜ openssl asn1parse -in private.p8.key
    0:d=0  hl=3 l= 135 cons: SEQUENCE
    3:d=1  hl=2 l=   1 prim: INTEGER           :00  #表示版本号
    6:d=1  hl=2 l=  19 cons: SEQUENCE
    8:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey # 密钥算法标识,这里代表ec
   17:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1 # 椭圆曲线算法曲线,这里表示为nist-p256
   27:d=1  hl=2 l= 109 prim: OCTET STRING      [HEX DUMP]:306B0201010420EC466BB7FF97955E1F61FB62D18CEB724F0ABD57681B330B2FBEC7DFFCEFA03DA14403420004347567FAC88DFAB51123C87D4D27598FA0D90CAAB7597115906638D060526CBC5CFEEF13E236F293F8B934A0F3375641EBA4188E856E264176843E8B59C90CE3 # 私钥内容(16进制形式)

总结

本文对密码学中常见的文件类型、编码类型及格式进行了归类说明,同时使用openssl对ec类型私钥的生成、格式转换以及asn1内部表示进行了简单分析,希望读着通过本文的学习,能够对密码学常见的公私钥编码有个初步的认识和了解。

posted @ 2023-05-25 17:05  warm3snow  阅读(333)  评论(0编辑  收藏  举报