zoukankan      html  css  js  c++  java
  • RSA知识记录

    使用openssl生成秘钥对

    1.生成私钥, 长度1024bit, 格式pkcs1:

    openssl genrsa -out private_key.pem 1024

     pkcs1 长度为824(包含回车)

    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQDYnawB2RgjWmh7Nst78sukhLXhighCFNHkWEZzhtfQNx2ixoBg
    TZaCaPxRHcYYRTLO48d2ruaWImuB8Ld45iETINNlSPOC+mVnm5eYvCPVxwrHNP6p
    c2ZZUpIPn7GJqZzSwlXZCOwMbLLGKMNnaPBSDJ5jsl7huQvOt7Ig/5EZDQIDAQAB
    AoGAVRfzZzJyMgkk/Co1W3awmutrS7NetR7aqTooSt/QzcGpCbWy3qH8GzTE0dTB
    ae1dHTsLs0rX2GijFQOL/5lfqhv6EOqXzONhOhPuf4F7ZZHYRkUT9yRFf7r01YpW
    HnARwgIJfx/pjArafA/x5oS//wuf0O0vQOdUCSTfcLyWWV0CQQDrux4Cetdn0Z+8
    hRadX2rZ7t5llk4pBZtAoIxwRQtZN5NBmH4h9VxevebXSNVVpDn6tMnRHOqzZGGS
    VYFioAefAkEA6z3MBtrCgsaO/fESwtlPD8Y0JmH17B2LBlBKZ7fmCODtQDXKk1m6
    Kcso0VM1e7sHGZINLUZ6fdqSam9KqfeP0wJAEaktMGZfqQmNfCREc3nomXdJ9jZy
    mKQw44CjxO2HUiHVyH5SRN0LFJYJq2trgEUTivLsg9w0wUft/3akgO0YZQJBAJmI
    7d8TbJyaJ73KWCpgVt++x0695RpEdfaa9NUZC8SDuZWNBjiB+aVJecyVeHTXLt0b
    nAoO0+fMfn+FP8ALWg0CQQCEOA9JHwSy4DQePDJ9hMHn2f5SReQYJZnW6fgbQm4k
    8gffz2BZCrKvTIwfQ/PI/52hZVuZOi+B7iWYKAsV7QNd
    -----END RSA PRIVATE KEY-----

    2.将生成的私钥转换成pkcs8格式:

    openssl pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt -out pkcs8_private_key.pem

    pkcs8 长度为861(包含回车)

    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANidrAHZGCNaaHs2
    y3vyy6SEteGKCEIU0eRYRnOG19A3HaLGgGBNloJo/FEdxhhFMs7jx3au5pYia4Hw
    t3jmIRMg02VI84L6ZWebl5i8I9XHCsc0/qlzZllSkg+fsYmpnNLCVdkI7AxsssYo
    w2do8FIMnmOyXuG5C863siD/kRkNAgMBAAECgYBVF/NnMnIyCST8KjVbdrCa62tL
    s161HtqpOihK39DNwakJtbLeofwbNMTR1MFp7V0dOwuzStfYaKMVA4v/mV+qG/oQ
    6pfM42E6E+5/gXtlkdhGRRP3JEV/uvTVilYecBHCAgl/H+mMCtp8D/HmhL//C5/Q
    7S9A51QJJN9wvJZZXQJBAOu7HgJ612fRn7yFFp1fatnu3mWWTikFm0CgjHBFC1k3
    k0GYfiH1XF695tdI1VWkOfq0ydEc6rNkYZJVgWKgB58CQQDrPcwG2sKCxo798RLC
    2U8PxjQmYfXsHYsGUEpnt+YI4O1ANcqTWbopyyjRUzV7uwcZkg0tRnp92pJqb0qp
    94/TAkARqS0wZl+pCY18JERzeeiZd0n2NnKYpDDjgKPE7YdSIdXIflJE3QsUlgmr
    a2uARROK8uyD3DTBR+3/dqSA7RhlAkEAmYjt3xNsnJonvcpYKmBW377HTr3lGkR1
    9pr01RkLxIO5lY0GOIH5pUl5zJV4dNcu3RucCg7T58x+f4U/wAtaDQJBAIQ4D0kf
    BLLgNB48Mn2EwefZ/lJF5Bglmdbp+BtCbiTyB9/PYFkKsq9MjB9D88j/naFlW5k6
    L4HuJZgoCxXtA10=
    -----END PRIVATE KEY-----

    3.将pkcs8格式转换成pkcs1格式:

    openssl rsa -in pkcs8_private_key.pem -out pkcs1_private_key.pem

    转换的结果和步骤1生成的结果是一致的。

    4.从pkcs1私钥中生成pkcs8公钥

    openssl rsa -in pkcs1_private_key.pem -pubout -out public_key.pem

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYnawB2RgjWmh7Nst78sukhLXh
    ighCFNHkWEZzhtfQNx2ixoBgTZaCaPxRHcYYRTLO48d2ruaWImuB8Ld45iETINNl
    SPOC+mVnm5eYvCPVxwrHNP6pc2ZZUpIPn7GJqZzSwlXZCOwMbLLGKMNnaPBSDJ5j
    sl7huQvOt7Ig/5EZDQIDAQAB
    -----END PUBLIC KEY-----

    5. 从pkcs8私钥中生成pkcs8公钥
    openssl rsa -in pkcs8_private_key.pem -pubout -out public_pkcs8.pem

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYnawB2RgjWmh7Nst78sukhLXh
    ighCFNHkWEZzhtfQNx2ixoBgTZaCaPxRHcYYRTLO48d2ruaWImuB8Ld45iETINNl
    SPOC+mVnm5eYvCPVxwrHNP6pc2ZZUpIPn7GJqZzSwlXZCOwMbLLGKMNnaPBSDJ5j
    sl7huQvOt7Ig/5EZDQIDAQAB
    -----END PUBLIC KEY-----

    步骤5和步骤4生成的结果是一致的。

    6. pkcs8公钥转pkcs1公钥

    openssl rsa -pubin -in public_pkcs8.pem -RSAPublicKey_out -out public_pkcs1.pem

    -----BEGIN RSA PUBLIC KEY-----
    MIGJAoGBANOWVQXwOaDvutmQtcgRC2KAImxy34x8QiK0/L88dbrwvZIMeqmxXXHa
    cBIDuVyzMd7k+SOg9e0f8wcHG37T8Y18PlM/tkWV5l+woe8Cj+5O6jt7y+57DzfV
    WQuItI5VKYCJBvmjSrwRB5I9hFmMVh3NRLH3NYR4wbngG66GFiubAgMBAAE=
    -----END RSA PUBLIC KEY-----

    7. pkcs1公钥转换为pkcs8公钥

    openssl rsa -RSAPublicKey_in -in pub_pkcs1.pem -pubout -out public_pkcs8_new.pem

    步骤7和步骤4,5 生成的结果是一致的。

    -PKCS#8密钥格式,多用于JAVA、PHP, iOS程序加解密中,为目前用的比较多的密钥、证书格式,也用于微信RSA等程序,格式为

    -----BEGIN RSA XXX KEY-----
    BASE64 ENCODED DATA
    -----END RSA XXX KEY-----

    -PKCS#1密钥格式,多用于openssl,JS等其它程序加解密,属于比较老的格式标准,格式为

    -----BEGIN XXX KEY-----
    BASE64 ENCODED DATA
    -----END XXX KEY-----

    - 根据私钥可以导出公钥,根据公钥则不能导出私钥

    秘钥解析

    PKCS#8/PKCS#1格式的密钥使用BASE64方式进行编码,可以使用如下网站进行解码:

    https://the-x.cn/base64

    将密钥文件(以PKCS#8私钥文件为例)去头去尾以后,放入文本框进行解析,可以看到如下结果:

    从结果中可以看出,pem格式的密钥文件首先基于asn.1进行数据编码。

    ASN.1(=Abstract Syntax Notation One),是一种结构化的描述语言,包括两部分,数据描述语言和数据编码规则。

    • 数据描述语言标准:语言标准允许用户自定义的基本数据类型,并可以通过简单的数据类型组成更复杂的数据类型。
    • 数据编码规则:这些编码方法规定了将数字对象转换成应用程序能够处理、保存、传输的二进制形式的一组规则。

    标准ASN.1编码规则有规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML Encoding Rules)。

    所谓的规则,就是数据流编解码的方式。编码:将数据结构(可能是不同的,异构的)变成数据流;解码:其他应用读取解析,获得相应数据。

    openssl使用的是asn.1的der编码规则,保证每个asn.1对象使用der编码获得的二进制编码是唯一的。因为DER是纯二进制格式,对人不友好,所以openssl一般都用PEM进行存储。

    PEM和DER的关系如下图所示,其中几种加密环节是可选的。

     
     
    所以从本质上来说,openssl的PEM编码就是在DER编码的技术上进行Base64编码,然后添加一些头尾信息组成,可以通过openssl指令对DER和PEM 进行格式转换。

    DER

    DER就是密钥的二进制表述格式。

    Distinguished Encoding Rules (DER) is a binary serialization of ASN.1 format. It is often used for cryptographic data such as certificates, but has other uses.

    PEM

    PEM格式就是对DER编码转码为base64字符格式。通过base64解码可以还原DER格式。

    A PEM file is plain text. It contain one or more objects, such as certificates or keys, which may not all be the same type. Each object is delimited by lines similar to “—–BEGIN …—–” and “—–END …—–”. Data that is not between such lines is ignored, and is sometimes used for comments, or for a human-readable dump of the encoded data.

    Following the “BEGIN” and “END” keywords is a name (such as “CERTIFICATE”) that can be used as an identifier for the type of object.

    The data between the delimiter lines starts with an optional email-like header section, followed by base64-encoded payload data. After decoding, the payload data is in DER format.

    PEM 是明文格式,可以包含证书或者是密钥;其内容通常是以类似 “—–BEGIN …—–” 开头 “—–END …—–” 为结尾的这样的格式进行描述的。


    ASN编码解析- 公钥PEM

    PKCS #1

    PKCS #1 标准是专门为 RSA 密钥进行定义的,其对应的 PEM 文件格式如下,

    -----BEGIN RSA PUBLIC KEY-----
    BASE64 ENCODED DATA
    -----END RSA PUBLIC KEY-----
    
    

    上面的内容 BASE64 ENCODED DATA 指的就是 ANS.1 的 DER 的 Base64 编码。其ASN.1的格式为:

    RSAPublicKey ::= SEQUENCE {
        modulus           INTEGER,  -- n
        publicExponent    INTEGER   -- e
    }
    

    各个filed的含义:

    • modulus 是RSA的合数模n。
    • publicExponent 是RSA公开幂e。
    PKCS #8

    PKCS#8 标准定义了一个密钥格式的通用方案,它不仅仅为 RSA 所使用,同样也可以被其它密钥所使用。其对应的PEM文件格式如下:

    -----BEGIN PUBLIC KEY-----
    BASE64 ENCODED DATA
    -----END PUBLIC KEY-----
    

    注意,这里就没有 RSA 字样了,因为 PKCS#8 是一个通用型的秘钥格式方案;其中的 BASE64 ENCODED DATA 所标注的内容为 PEM 格式中对 DER 原始二进制进行的 BASE64 编码:

    PublicKeyInfo ::= SEQUENCE {
      algorithm       AlgorithmIdentifier,
      PublicKey       BIT STRING
    }
    AlgorithmIdentifier ::= SEQUENCE {
      algorithm       OBJECT IDENTIFIER,
      parameters      ANY DEFINED BY algorithm OPTIONAL
    }
    

    PKCS#8 虽然名字叫做 Private-Key Information Syntax Specification,但是实际上,可以看到,它同样可以用作 Public Key 的格式定义;而 PKCS#8 是站在 PKCS#7 CMS 的基础之上进行编码格式定义的。

     

    ASN编码解析- 私钥PEM

    PKCS #1

    PKCS#1 是专门为 RSA 所涉及的,其对应的 PEM 格式如下:

    -----BEGIN RSA PRIVATE KEY-----
    BASE64 ENCODED DATA
    -----END RSA PRIVATE KEY-----
    

    原始的 DER 格式结构,既是 ASN.1 的数据结构:

    RSAPrivateKey ::= SEQUENCE {
      version           Version,
      modulus           INTEGER,  -- n
      publicExponent    INTEGER,  -- e
      privateExponent   INTEGER,  -- d
      prime1            INTEGER,  -- p
      prime2            INTEGER,  -- q
      exponent1         INTEGER,  -- d mod (p-1)
      exponent2         INTEGER,  -- d mod (q-1)
      coefficient       INTEGER,  -- (inverse of q) mod p
      otherPrimeInfos   OtherPrimeInfos OPTIONAL
    }
    

    其中各个字段的含义为:

    • version 是版本号,两个素数为0,如果使用了多素数,则版本号应该是1。
      Version ::= INTEGER { two-prime(0), multi(1) }
      (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
    • modulus 是RSA合数模n。
    • publicExponent 是RSA的公开幂e。
    • privateExponent 是RSA的私有幂d。
    • prime1 是n的素数因子p。
    • prime2 是n的素数因子q。
    • exponent1 等于d mod (p − 1)。
    • exponent2 等于d mod (q − 1)。
    • coefficient 是CRT系数 q–1 mod p。
    • otherPrimeInfos 按顺序包含了其它素数r3, …, ru的信息。如果version是0 ,它应该被忽略;而如果version是1,它应该至少包含OtherPrimeInfo的一个实例。
     
    PKCS #8
    未加密

    PEM格式:

    -----BEGIN PRIVATE KEY-----
    BASE64 ENCODED DATA
    -----END PRIVATE KEY-----
    

    对应的DER:

    PrivateKeyInfo ::= SEQUENCE {
      version         Version,
      algorithm       AlgorithmIdentifier,
      PrivateKey      BIT STRING
    }
    AlgorithmIdentifier ::= SEQUENCE {
      algorithm       OBJECT IDENTIFIER,
      parameters      ANY DEFINED BY algorithm OPTIONAL
    }
    
    加密

    针对私钥的内容进行加密。
    PEM格式:

    -----BEGIN ENCRYPTED PRIVATE KEY-----
    BASE64 ENCODED DATA
    -----END ENCRYPTED PRIVATE KEY-----
    

    DER格式:

    EncryptedPrivateKeyInfo ::= SEQUENCE {
      encryptionAlgorithm  EncryptionAlgorithmIdentifier,
      encryptedData        EncryptedData
    }
    EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
    EncryptedData ::= OCTET STRING
    

     

    使用命令解析私钥

    使用asn1parse命令读取私钥SAN.1结构,其中-i表示使用缩进格式。

    openssl asn1parse -i -in privatekey.pem 
    

    其ASN.1输出格式为:

        0:d=0  hl=3 l= 135 cons: SEQUENCE          
        3:d=1  hl=2 l=   1 prim:  INTEGER           :01
        6:d=1  hl=2 l=  19 cons:  SEQUENCE          
        8:d=2  hl=2 l=   7 prim:   OBJECT            :id-ecPublicKey
       17:d=2  hl=2 l=   8 prim:   OBJECT            :prime256v1
       27:d=1  hl=2 l= 109 prim:  OCTET STRING      [HEX DUMP]:306B02010104204B42FE59E4C16B8BDD516E23AE880BBBC2662D28DD6B461C0364D639F691FBCCA144034200040EE3526C590136A6DD9467F0C17487296BF8A70D9E14E783F955C21D5E0212B04A9D45C18B073F9CBEFAE94CD79D69EC8D4529DD9392CC209FE7A70D90B9AFE9
    

    每一行的意义大概为:

    • 0 表示节点在整个文件中的偏移长度
    • d=0 表示节点深度
    • hl=3 表示节点头字节长度
    • l=135 表示节点数据字节长度
    • cons 表示该节点为结构节点,表示包含子节点或者子结构数据
    • prim 表示该节点为原始节点,包含数据
    • SEQUENCE、OCTET STRING等都是ASN.1中定义的数据类型,具体可以参考ASN.1格式说明

    最后一个节点OCTET STRING [HEX DUMP],就是加密后的私钥数据。

     openssl rsa -in privatekey.pem -noout -text

     解析ASN.1格式中每个段的数据值

    $ openssl rsa -in ke.pem -noout -text
    RSA Private-Key: (1024 bit, 2 primes)
    modulus:
        00:d8:9d:ac:01:d9:18:23:5a:68:7b:36:cb:7b:f2:
        cb:a4:84:b5:e1:8a:08:42:14:d1:e4:58:46:73:86:
        d7:d0:37:1d:a2:c6:80:60:4d:96:82:68:fc:51:1d:
        c6:18:45:32:ce:e3:c7:76:ae:e6:96:22:6b:81:f0:
        b7:78:e6:21:13:20:d3:65:48:f3:82:fa:65:67:9b:
        97:98:bc:23:d5:c7:0a:c7:34:fe:a9:73:66:59:52:
        92:0f:9f:b1:89:a9:9c:d2:c2:55:d9:08:ec:0c:6c:
        b2:c6:28:c3:67:68:f0:52:0c:9e:63:b2:5e:e1:b9:
        0b:ce:b7:b2:20:ff:91:19:0d
    publicExponent: 65537 (0x10001)
    privateExponent:
        55:17:f3:67:32:72:32:09:24:fc:2a:35:5b:76:b0:
        9a:eb:6b:4b:b3:5e:b5:1e:da:a9:3a:28:4a:df:d0:
        cd:c1:a9:09:b5:b2:de:a1:fc:1b:34:c4:d1:d4:c1:
        69:ed:5d:1d:3b:0b:b3:4a:d7:d8:68:a3:15:03:8b:
        ff:99:5f:aa:1b:fa:10:ea:97:cc:e3:61:3a:13:ee:
        7f:81:7b:65:91:d8:46:45:13:f7:24:45:7f:ba:f4:
        d5:8a:56:1e:70:11:c2:02:09:7f:1f:e9:8c:0a:da:
        7c:0f:f1:e6:84:bf:ff:0b:9f:d0:ed:2f:40:e7:54:
        09:24:df:70:bc:96:59:5d
    prime1:
        00:eb:bb:1e:02:7a:d7:67:d1:9f:bc:85:16:9d:5f:
        6a:d9:ee:de:65:96:4e:29:05:9b:40:a0:8c:70:45:
        0b:59:37:93:41:98:7e:21:f5:5c:5e:bd:e6:d7:48:
        d5:55:a4:39:fa:b4:c9:d1:1c:ea:b3:64:61:92:55:
        81:62:a0:07:9f
    prime2:
        00:eb:3d:cc:06:da:c2:82:c6:8e:fd:f1:12:c2:d9:
        4f:0f:c6:34:26:61:f5:ec:1d:8b:06:50:4a:67:b7:
        e6:08:e0:ed:40:35:ca:93:59:ba:29:cb:28:d1:53:
        35:7b:bb:07:19:92:0d:2d:46:7a:7d:da:92:6a:6f:
        4a:a9:f7:8f:d3
    exponent1:
        11:a9:2d:30:66:5f:a9:09:8d:7c:24:44:73:79:e8:
        99:77:49:f6:36:72:98:a4:30:e3:80:a3:c4:ed:87:
        52:21:d5:c8:7e:52:44:dd:0b:14:96:09:ab:6b:6b:
        80:45:13:8a:f2:ec:83:dc:34:c1:47:ed:ff:76:a4:
        80:ed:18:65
    exponent2:
        00:99:88:ed:df:13:6c:9c:9a:27:bd:ca:58:2a:60:
        56:df:be:c7:4e:bd:e5:1a:44:75:f6:9a:f4:d5:19:
        0b:c4:83:b9:95:8d:06:38:81:f9:a5:49:79:cc:95:
        78:74:d7:2e:dd:1b:9c:0a:0e:d3:e7:cc:7e:7f:85:
        3f:c0:0b:5a:0d
    coefficient:
        00:84:38:0f:49:1f:04:b2:e0:34:1e:3c:32:7d:84:
        c1:e7:d9:fe:52:45:e4:18:25:99:d6:e9:f8:1b:42:
        6e:24:f2:07:df:cf:60:59:0a:b2:af:4c:8c:1f:43:
        f3:c8:ff:9d:a1:65:5b:99:3a:2f:81:ee:25:98:28:
        0b:15:ed:03:5d

     

    使用命令解析公钥(加入-pubin选项表示公钥)

    openssl rsa -pubin -in pub.pem -noout -text

     openssl rsa -pubin -in pub.pem -noout -text
    RSA Public-Key: (1024 bit)
    Modulus:
        00:d3:96:55:05:f0:39:a0:ef:ba:d9:90:b5:c8:11:
        0b:62:80:22:6c:72:df:8c:7c:42:22:b4:fc:bf:3c:
        75:ba:f0:bd:92:0c:7a:a9:b1:5d:71:da:70:12:03:
        b9:5c:b3:31:de:e4:f9:23:a0:f5:ed:1f:f3:07:07:
        1b:7e:d3:f1:8d:7c:3e:53:3f:b6:45:95:e6:5f:b0:
        a1:ef:02:8f:ee:4e:ea:3b:7b:cb:ee:7b:0f:37:d5:
        59:0b:88:b4:8e:55:29:80:89:06:f9:a3:4a:bc:11:
        07:92:3d:84:59:8c:56:1d:cd:44:b1:f7:35:84:78:
        c1:b9:e0:1b:ae:86:16:2b:9b
    Exponent: 65537 (0x10001)

    openssl asn1parse -in pubkey.pem -strparse 18

    rsa加密的public key格式有多种,常见的有两种,一种密钥头为‘-----BEGIN RSA PUBLIC KEY-----’,一种开头为‘-----BEGIN PUBLIC KEY-----’,二者分别对应rsa的PKCS#1和PKCS#8格式。
    使用openssl库加载rsa的公钥时,使用的函数也不同。以字符串公钥为例,对PKCS#1格式的密钥加载使用PEM_read_bio_RSAPublicKey()函数,对PKCS#8格式公钥的加载使用PEM_read_bio_RSA_PUBKEY()函数。

    ===============================================

    本文引用:

    1. https://www.jianshu.com/p/78886e480bef

    2.https://blog.csdn.net/lucien_cc/article/details/18407451/

    3.https://www.cnblogs.com/cocoajin/p/10510574.html

  • 相关阅读:
    《数据库技术基础与应用(第2版)》学习笔记——第4章
    《数据库技术基础与应用(第2版)》学习笔记——第4章
    《数据库技术基础与应用(第2版)》学习笔记——第3章
    《数据库技术基础与应用(第2版)》学习笔记——第3章
    《数据库技术基础与应用(第2版)》学习笔记——第2章
    《数据库技术基础与应用(第2版)》学习笔记——第2章
    《数据库技术基础与应用(第2版)》学习笔记——第1章
    《数据库技术基础与应用(第2版)》学习笔记——第1章
    新近碰到的病毒(TR.Spy.Babonock.A)
    新近碰到的病毒(TR.Spy.Babonock.A)
  • 原文地址:https://www.cnblogs.com/DF11G/p/13597069.html
Copyright © 2011-2022 走看看