12.3.?PGP加密函数

12.3.1. pgp_sym_encrypt()
12.3.2. pgp_sym_decrypt()
12.3.3. pgp_pub_encrypt()
12.3.4. pgp_pub_decrypt()
12.3.5. pgp_key_id()
12.3.6. armor(), dearmor()
12.3.7. pgp_armor_headers
12.3.8. PGP函数的选项
12.3.9. 用GnuPG生成PGP密钥
12.3.10. PGP代码的限制

函数实现了OpenPGP (RFC 4880) 标准的加密部分。对称密钥和公钥加密都支持。

一个加密的PGP消息由两个包组成:

使用对称密钥(即一个口令)加密时:

  1. 给定的口令被String2Key (S2K) 算法哈希。这更像crypt()算法 — 有目的地慢并且使用随机salt — 但是它会产生一个全长度的二进制密钥。

  2. 如果要求一个独立的会话密钥,将会生成一个新的随机密钥。否则S2K密钥将被直接用作会话密钥。

  3. 如果直接使用S2K密钥,那么只有S2K设置将被放入会话密钥包中,否则会话密钥会用S2K密钥加密并且放入会话密钥包中。

使用公钥加密时:

  1. 一个新的随机会话密钥会被生成。

  2. 它被用公共密钥加密并且放入到会话密钥包中。

在两种情况下,要被加密的数据按下列步骤被处理:

  1. 可选的数据操纵:压缩、转换成UTF-8或者行末转换。

  2. 数据会被加上一个随机字节的块作为前缀。这等效于使用一个随机IV。

  3. 追加一个随机前缀和数据的SHA1哈希。

  4. 所有这些都用会话密钥加密并且放在数据包中。

12.3.1.?pgp_sym_encrypt()

pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea

pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea

使用对称PGP密钥psw加密data。

options参数包含下文所述的选项设置。

12.3.2.?pgp_sym_decrypt()

pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text

pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea

解密用对称密钥加密过的PGP消息。

不允许使用pgp_sym_decrypt解密bytea数据。这是为了避免输出非法的字符数据。可以使用pgp_sym_decrypt_bytea解密原始文本数据。

options参数可以包含下文所述的选项设置。

12.3.3.?pgp_pub_encrypt()

pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea

pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea

用一个公共PGP密钥key加密data。给这个函数一个私钥会产生错误。

options参数可以包含下文所述的选项设置。

12.3.4.?pgp_pub_decrypt()

pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text

pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea

解密一个公共密钥加密的消息。key必须是用来加密的公钥对应的私钥。如果私钥是用口令保护的,必须在psw中给出该口令。如果没有口令,但想指定选项,需要给出一个空口令。

不允许使用pgp_pub_decrypt解密bytea数据。这是为了避免输出非法的字符数据。可以使用pgp_pub_decrypt_bytea解密原始文本数据。

options参数可以包含下文所述的选项设置。

12.3.5.?pgp_key_id()

pgp_key_id(bytea) returns text

pgp_key_id抽取一个PGP公钥或私钥的密钥ID。或者如果给定了一个加密过的消息,它将给出一个用来加密数据的密钥ID。

pgp_key_id能够返回2个特殊密钥ID:

  • SYMKEY:该消息是用对称密钥加密的。

  • ANYKEY:该消息是用公钥加密的,但是密钥ID已经被移除。这意味着需要尝试所有的密钥来看看哪个能解密该消息。uxcrypto本身不产生这样的消息。

注意

不同的密钥可能具有相同的ID。这很少见但属于正常事件。客户端应用应尝试用每一个去解密,看看哪个合适 — 类似ANYKEY。

12.3.6.?armor(), dearmor()

armor(data bytea [ , keys text[], values text[] ]) returns text

dearmor(data text) returns bytea

这些函数把二进制数据封装/解包成PGP ASCII-armored格式,其基本上是带有CRC和额外格式化的Base64。

如果指定了keys和values数组,每一个键/值对的armored格式上会增加一个armor header。两个数组都必须是单一维度的,长度必须相同。键和值不能包含任何非ASCII字符。

12.3.7.?pgp_armor_headers

pgp_armor_headers(data text, key out text, value out text) returns setof record

pgp_armor_headers()从data中抽取armor header。返回值是一个有两列的行集合,包括键和值。如果键或值包含任何非ASCII字符,会被视作UTF-8。

12.3.8.?PGP函数的选项

选项被命名为与GnuPG类似的形式。一个选项的值应该在一个等号后给出,各个选项之间用逗号分隔。例如:

pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256')

除了convert-crlf之外所有这些选项只适用于加密函数。解密函数会从PGP数据中得到这些参数。

  1. cipher-algo

    要用哪个密码算法。

    值:bf, aes128, aes192, aes256 (只用于OpenSSL:3des, cast5)

    默认:aes128

    适用于:pgp_sym_encrypt, pgp_pub_encrypt

  2. convert-crlf

    加密时是否把\n转换成\r\n以及解密时是否把\r\n转换成\n。RFC 4880指定文本数据存储时应该使用\r\n换行。使用这个选项能够得到完全RFC兼容的行为。

    值:0, 1

    默认:0

    适用于:pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt

  3. disable-mdc

    不用SHA-1保护数据。使用这个选项的好处是实现与古董级别PGP产品的兼容,这些产品在受SHA-1保护的包被加入到RFC 4880之前就已经存在了。

    值:0,1

    默认:0

    适用于:pgp_sym_encrypt, pgp_pub_encrypt

  4. sess-key

    使用单独的会话密钥。公钥加密总是使用一个单独的会话密钥。这个选项是用于对称密钥加密的,对称密钥加密默认直接使用S2K密钥。

    值:0,1

    默认:0

    适用于:pgp_sym_encrypt

  5. s2k-mode

    值:

    0 - 不用salt。这种做法十分危险!

    1 - 用salt但是使用固定的迭代计数。

    3 - 可变的迭代计数。

    默认:3

    适用于:pgp_sym_encrypt

  6. s2k-count

    S2K算法要使用的迭代次数。它必须是一个位于1024和65011712之间的值,首尾两个值包括在内。

    默认:65536和253952之间的一个随机值。

    适用于:pgp_sym_encrypt,只能用于s2k-mode=3。

  7. s2k-digest-algo

    要在S2K计算中使用哪种摘要算法。

    值:md5, sha1

    默认:sha1

    适用于:pgp_sym_encrypt

  8. s2k-cipher-algo

    要用哪种密码来加密独立的会话密钥。

    值:bf, aes, aes128, aes192, aes256

    默认:use cipher-algo

    适用于:pgp_sym_encrypt

  9. unicode-mode

    是否把文本数据在数据库内部编码和UTF-8之间来回转换。如果数据库已经是UTF-8,将不会转换,但是消息将被标记为UTF-8。没有这个选项它将不会被标记。

    值:0,1

    默认:0

    适用于:pgp_sym_encrypt, pgp_pub_encrypt

12.3.9.?用GnuPG生成PGP密钥

  • 生成一个新密钥:

    gpg --gen-key

    更好的密钥类型是“DSA和Elgamal”。

    对于RSA密钥,必须创建仅用于签名的DSA或RSA密钥作为主控密钥,然后用gpg --edit-key增加一个RSA加密子密钥。

  • 列举密钥:

    gpg --list-secret-keys
  • 以ASCII-armor格式导出一个公钥:

    gpg -a --export KEYID > public.key
  • 以ASCII-armor格式导出一个私钥:

    gpg -a --export-secret-keys KEYID > secret.key

在把这些密钥交给PGP函数之前,需要对它们使用dearmor()。或者如果能处理二进制数据,可以从命令中去掉-a。

12.3.10.?PGP代码的限制

  • 不支持签名。这也意味着它不检查加密子密钥是否属于主控密钥。

  • 不支持加密密钥作为主控密钥。由于通常并不鼓励那种用法,这应该不属于严重的问题。

  • 不支持多个子密钥。在实践中普遍需要多个子密钥。并且,不能把常规GPG/PGP密钥用于uxcrypto,而是创建一些新的密钥,因为使用场景不同。

XML 地图 | Sitemap 地图