我正在使用Python的pkcs11包来访问存储在Yubikey 5上的X.509证书。使用pkcs11对象访问证书、公钥和私钥以及签名和验证签名都正常工作。然而,我无法理解为什么使用公钥进行加密不起作用。以下是我的代码:
import pkcs11
from pkcs11 import Attribute, ObjectClass, KeyType, util
lib = pkcs11.lib('/usr/lib/x86_64-linux-gnu/pkcs11/onepin-opensc-pkcs11.so')
token = lib.get_token(token_label='PIV Card Holder pin (PIV_II)'
session = token.open(user_pin=pin)
# Getting a private and a public key as pkcs11 Object
private = next(session.get_objects({
Attribute.CLASS: ObjectClass.PRIVATE_KEY,
}))
public = next(session.get_objects({
Attribute.CLASS: ObjectClass.PUBLIC_KEY,
}))
data = 'Hello, world!'
sig = private.sign(data) # Works!
sig_verif = public.verify(data, sig) # Works!
print("Signature is valid? "+str(sig_verif)) # True
# So far, everything above worked fine.
# ----------
# Now, this is the part that does not work
encrypt_data = public.encrypt(data) # Fails!
上述最后一行代码报错,错误提示为pkcs11.exceptions.FunctionNotSupported。我做了一些调查研究,发现可能是因为我使用的openSC库文件(*.so)不支持此函数(encrypt)。但考虑到签名功能可以正常使用,这一点令人难以置信。
为确保我可以在会话上下文之外使用该特定公钥,我尝试了使用Crypto包的以下代码:
from Crypto.Cipher import PKCS1_OAEP
public_key = RSA.importKey(public[Attribute.VALUE]) # The content of pkcs11 public key as DER
cipher = PKCS1_OAEP.new(public_key)
encr_data = cipher.encrypt(data) # This works!
看起来,使用我的独立公钥可以加密数据。但为什么我不能在 pkcs11 令牌会话的上下文中这么做呢?
然后,我尝试使用 pkcs11 对象解密函数来解密使用上面的 Crypto 模块生成的数据:
decrypted = private.decrypt(encr_data) # It fails!
上述操作失败,出现了pkcs11.exceptions.MechanismInvalid错误。我尝试使用不同的机制,但所有的结果都导致相同的错误。有趣的是——看起来pkcs11对象允许我调用decrypt函数而不会抱怨它不被支持。
还有一件事我应该提到。我检查了我的证书,并在扩展 -> 证书密钥用途下看到:
Critical
Signing
Key Encipherment
我了解了“密钥加密”和“数据加密”的区别,并了解到“密钥加密”用于加密秘密(对称)密钥而不是数据。这可能是我不能为此令牌会话使用“加密”函数的原因吗?
任何反馈都将不胜感激!
Encrypt
和Decrypt
。你正在尝试加密操作的公钥是否启用了这些属性? - always_a_rookie