使用 BCPG 公钥时 PGPy 抛出错误

问题描述

我是 PGP 加密的新手,我正在尝试了解我遇到的问题。我有这个公钥(取自一些在线示例)

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG v1.58

mI0EWiOMeQEEaimCEQUnSQ54ee+mnkANsjyvZm2QsC1sgiBEpmyJbh2xWuluJ/KV
TIUSqbkLOEq4COIlzG0fhuruUWBM2+ANazq5jkxLrYmHX4AwA2Q6jvd3xE8B1uVj
qT0TEKyZtmBwesEswUxb+vOwVLdWKxpcySXtIQhoKWAUVzG7e5uEawyXABEBAAG0
BWFuaXNoiJwEEAECAAYFAlojjHkACgkQmCS94uDDx9lHewP/UtsSk3lyj5GnHyoT
HZMz+sUFpFlan7agqHf6pV2Pgdb9OMCVauMwl9bjPY9HSHQg/a3gTQ5qNq9txiI2
4Fso2Q3AR6XcVk2wQxS6prJ9imPi1npXarCwZkEgWLXWLuQLHoxRWHf9olUqeW7P
kwQlJ1K9Ib85pCTvx16DN7QwQv8=
=Qteg
-----END PGP PUBLIC KEY BLOCK-----

使用此代码

pub_key = pgpy.PGPKey()
pub_key.parse(KEY_PUB)

SOME_TEXT = 'Hello,world'

msg = pgpy.PGPMessage.new(SOME_TEXT)

encrypted_message = pub_key.encrypt(msg)

pgpstr = str(encrypted_message)

print(pgpstr)

我收到此错误

pgpy.errors.PGPError: Key 9824BDE2E0C3C7D9 does not have the required usage flag EncryptStorage,EncryptCommunications

但是如果我使用另一个键,一切都会正常:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: Alice's OpenPGP certificate
Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html

mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
=iIGO
-----END PGP PUBLIC KEY BLOCK-----

所以我想了解这两个键之间有什么区别,以及如何使第一个起作用。提前致谢!

解决方法

错误消息明确告诉您失败的密钥并没有将其描述为适合加密存储或通信。

根据 the signature subpacket specification,我们知道此信息存在于类型为 27 的子数据包中。

根据 the detailed specification on that subpacket,我们知道所需的标志分别是 0x04 和 0x08。


要比较这些键,您可以使用 gpg --list-packets --verbose

对于第一个非工作密钥,我们得到:

gpg: armor header: Version: BCPG v1.58
# off=0 ctb=98 tag=6 hlen=2 plen=141
:public key packet:
        version 4,algo 1,created 1512279161,expires 0
        pkey[0]: 8982110527490E7879EFA69E400DB23CAF666D90B02D6C188044A66C896E1DB15AE96E27F2954C8512A9B90B384AB808E225CC6D1F86EAEE51604CDBE00D6B3AB98E4C4BAD89875F803003643A8EF777C44F01D6E563A93D1310AC99B660707AC12CC14C5BFAF3B054B756297A5CC925ED2108682960145731BB7B9B846B0C97
        pkey[1]: 010001
        keyid: 9824BDE2E0C3C7D9
# off=143 ctb=b4 tag=13 hlen=2 plen=5
:user ID packet: "anish"
# off=150 ctb=88 tag=2 hlen=2 plen=156
:signature packet: algo 1,keyid 9824BDE2E0C3C7D9
        version 4,md5len 0,sigclass 0x10
        digest algo 2,begin of digest 47 7b
        hashed subpkt 2 len 4 (sig created 2017-12-03)
        subpkt 16 len 8 (issuer key ID 9824BDE2E0C3C7D9)
        data: 52DB129379728F91A71F2A131D9333FAC505A4595A9FB6A0A877FAA55D8F81D6FD38C0956AE33097D6E33D8F47487420FDADE04D0E6A36AF6DC62236E05B28D90DC047A5DC564DB04314BAA6B27D8A63E2D67A576AB0B066412058B5D62EE40B1E8C515877FDA2552A796ECF9304252752BD21BF39A424EFC75E8337B43042FF

该密钥根本不包含类型为 27 的签名子包。


对于第二个工作密钥,我们得到:

gpg: armor header: Comment: Alice's OpenPGP certificate
gpg: armor header: Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html
# off=0 ctb=98 tag=6 hlen=2 plen=51
:public key packet:
        version 4,algo 22,created 1548158185,expires 0
        pkey[0]: 092B06010401DA470F01 ed25519 (1.3.6.1.4.1.11591.15.1)
        pkey[1]: 40AE35B0937140AB28856C504A4F84F35DC541A8F4C1DE09B3942FD46FB3B5BB5D
        keyid: F231550C4F47E38E
# off=53 ctb=b4 tag=13 hlen=2 plen=38
:user ID packet: "Alice Lovelace <alice@openpgp.example>"
# off=93 ctb=88 tag=2 hlen=2 plen=144
:signature packet: algo 22,keyid F231550C4F47E38E
        version 4,created 1571135290,sigclass 0x13
        digest algo 8,begin of digest e9 2b
        hashed subpkt 27 len 1 (key flags: 03)
        hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        hashed subpkt 23 len 1 (keyserver preferences: 80)
        hashed subpkt 33 len 21 (issuer fpr v4 EB85BB5FA33A75E15E944E63F231550C4F47E38E)
        hashed subpkt 2 len 4 (sig created 2019-10-15)
        subpkt 16 len 8 (issuer key ID F231550C4F47E38E)
        data: 039C7052A203A6B073AC77DA86B226698119CE772A6F6E6F90B5766AB61F6BBF
        data: 1DC0C2D2D0BE3C702C3BB3938754B54C2F51889B2F6B001F08F69066879DF202
# off=239 ctb=b8 tag=14 hlen=2 plen=56
:public sub key packet:
        version 4,algo 18,expires 0
        pkey[0]: 0A2B060104019755010501 cv25519 (1.3.6.1.4.1.3029.1.5.1)
        pkey[1]: 4042FF0621ADAB493CE0A9B5C2A430D8322291562B42B32DB4DF1DEC13DF9EBE22
        pkey[2]: 03010807
        keyid: 4766F6B9D5F21EB6
# off=297 ctb=88 tag=2 hlen=2 plen=120
:signature packet: algo 22,sigclass 0x18
        digest algo 8,begin of digest 59 d0
        hashed subpkt 33 len 21 (issuer fpr v4 EB85BB5FA33A75E15E944E63F231550C4F47E38E)
        hashed subpkt 2 len 4 (sig created 2019-01-22)
        hashed subpkt 27 len 1 (key flags: 0C)
        subpkt 16 len 8 (issuer key ID F231550C4F47E38E)
        data: C51D4B3A4C8731ACD4ED1191635059B53343C9D439E0FDC0D6E3137CD1FB27D1
        data: DB62ABED59028DE0040B4F15493795F9016C9B3E79FE59ED5A4C185A19AF3A01

这里配置的主密钥仅用于签名数据和认证其他密钥(值为3 == 2(签名数据)+ 1(认证其他密钥));但它有一个标志为 0x0C 的子密钥,又名十进制 12,又名 8(加密数据)+ 4(加密存储)。


最后,在 PGPy 中,encrypt 方法有一个装饰器 @KeyAction(KeyFlags.EncryptCommunications,KeyFlags.EncryptStorage,is_public=True),它实际上验证了有问题的标志。

可以想象,其中的 if len(self.flags) 子句旨在跳过对根本没有任何子数据包列表使用标志的密钥的检查。如果是这种情况,可以想象上述内容将被接受为错误报告,因为此代码正在对不存在使用数据的密钥执行使用检查。