代码之家  ›  专栏  ›  技术社区  ›  Siler

使用opensslapi读取公钥的密码回调

  •  2
  • Siler  · 技术社区  · 6 年前

    当使用公钥密码时,通常以加密格式存储私钥,因为它们当然应该是秘密的。这反映在opensslcapi中,它提供如下函数 PEM_write_PrivateKey ,它使用一个可选的密码作为函数参数来加密密钥(如AES)。然后,当从磁盘读回加密密钥时,opensslapi提供如下函数 PEM_read_PrivateKey

    但令我困惑的是,opensslapi似乎还允许用户在读取文件时提供密码回调 钥匙。例如,用于读取公钥的一个API函数签名是:

     EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
                                            pem_password_cb *cb, void *u);
    

    公众的

    1 回复  |  直到 6 年前
        1
  •  1
  •   Reinier Torenbeek    6 年前

    如中所述 this comment ,任何PEM编码的数据都可以加密。隐私增强邮件(PEM)的消息加密在中定义 RFC 1421 section 4.6 Summary of Encapsulated Header Fields

    -----BEGIN PRIVACY-ENHANCED MESSAGE-----
    Proc-Type: 4,ENCRYPTED
    Content-Domain: RFC822
    DEK-Info: DES-CBC,F8143EDE5960C597
    Originator-ID-Symmetric: linn@zendia.enet.dec.com,,
    Recipient-ID-Symmetric: linn@zendia.enet.dec.com,ptf-kmc,3
    Key-Info: DES-ECB,RSA-MD2,9FD3AAD2F2691B9A,
              B70665BB9BF7CBCDA60195DB94F727D3
    Recipient-ID-Symmetric: pem-dev@tis.com,ptf-kmc,4
    Key-Info: DES-ECB,RSA-MD2,161A3F75DC82EF26,
              E2EF532C65CBCFF79F83A2658132DB47
    
    LLrHB0eJzyhP+/fSStdW8okeEnv47jxe7SJ/iN72ohNcUk2jHEUSoH1nvNSIWL9M
    8tEjmF/zxB+bATMtPjCUWbz8Lr9wloXIkjHUlBLpvXR0UrUzYbkNpk0agV2IzUpk
    J6UiRRGcDSvzrsoK+oNvqu6z7Xs5Xfz5rDqUcMlK1Z6720dcBWGGsDLpTpSCnpot
    dXd/H5LMDWnonNvPCwQUHt==
    -----END PRIVACY-ENHANCED MESSAGE-----
    

    看看OpenSSL的1.1分支,它有一个函数 PEM_read_bio()

     int PEM_read_bio(BIO *in, char **name, char **header,
                      unsigned char **data, long *len);
    

    所有OpenSSL PEM_read_XYZ() 函数在某个时刻调用它,从 PEM_bytes_read_bio() ,因为它们都是通过宏扩展以相同的方式实现的。该函数包含以下调用:

    PEM_read_bio(bp, &nm, &header, &data, &len)
    

    把信息分开

    PEM_get_EVP_CIPHER_INFO(header, &cipher);
    

    找出在消息头中找到的加密信息类型并填写 EVP_CIPHER_INFO 反对,然后

    PEM_do_header(&cipher, data, &len, cb, u);
    

    根据发现的密码信息对数据进行解密——如果需要,也可以这样做。注意 cb 表示回调的参数,这是一种在需要时获取任何密码短语的输入的机制。

    现在可能令人困惑的是,某些私钥格式,例如PKCS#8,也有自己的机制,独立于PEM编码来存储加密信息。从技术上讲,应该可以对这些密钥应用两次加密:一次在PEM级别,一次在PKCS#8级别。不过,用于生成或转换为PKCS#8格式密钥的OpenSSL工具似乎没有提供这种选项。此外,这些工具似乎都没有公开加密任何生成的公钥PEM文件的选项,除非还包含私钥。

    你可以检查一些输出,看看他们是否符合我的故事。首先,生成PKCS#1格式的RSA密钥对,不加密:

    $ openssl genrsa
    Generating RSA private key, 2048 bit long modulus (2 primes)
    .................+++++
    ............+++++
    e is 65537 (0x010001)
    -----BEGIN RSA PRIVATE KEY-----
    MIIEpQIBAAKCAQEAlcnR/w7zPoLrhuqFvcfz5fn8DFb0fEcCKOKSj+x+JJxGth9P
    rJbxkt4pRXxbMIL0fX59HN5bRvQh2g59l/kfr30kCOnclap9nRrohWyg2i7720Cw
    <truncated>
    

    $ openssl genrsa -des3
    Generating RSA private key, 2048 bit long modulus (2 primes)
    .....................+++++
    ....................+++++
    e is 65537 (0x010001)
    Enter pass phrase:
    Verifying - Enter pass phrase:
    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,D90861647707F687
    
    DIupLghCjcvpLenqAAULaJj1EDvUUfc2Xc58YVh7rMTSVgLwZ+9CtnUQJcup4aUQ
    a1EdGXTadwBQB2jTtiFJbH67/5D26PHXPnM+YN2rnoReOExVS7hKu3DTq7c4j6a3
    <truncated>
    

    最后生成了一个类似的密钥,但现在是PKCS#8,PKCS#8有自己的加密,因此不能在PEM级别进行加密。您可以看到PEM标头不在那里。

    $ openssl genpkey -algorithm RSA -des3
    .........................................+++++
    ...........................................................................+++++
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIV0Ih4bsI6egCAggA
    MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECNOim8HAN8j5BIIEyEe05hHtc8HL
    <truncated>