title: Encrypting a data with a public key using pkcs11 module fails
body: <p>I am using Python's pkcs11 package to access an X.509 certificate stored on my Yubikey 5. Accessing the certificate, public and private keys using pkcs11 Objects work fine as is signing and signature verification. Howerver, for the life of me, I cannot figure out why encrypting with the public key does not work. Here is my code:</p>
  
  <pre><code>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!
  </code></pre>
  
  <p>The last line above fails with <strong>pkcs11.exceptions.FunctionNotSupported</strong> error. I did some research, and it the explanation I found seems to imply that this function (encrypt) is not supported by the openSC library file (*.so) that I am using. However, I find it hard to believe considering that signature feature works just fine. </p>
  
  <p>Just to make sure that I can use this particular public key outside of session context, I tried the following code using Crypto package:</p>
  
  <pre><code>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!
  </code></pre>
  
  <p>So, it seems that using my stand-alone public key allows me to encrypt data. But why can't I do it in the context of a pkcs11 token session? </p>
  
  <p>Then, I tried using the pkcs11 Object decrypt function to try to decrypt the data generated using Crypto module above:</p>
  
  <pre><code>decrypted = private.decrypt(encr_data) # It fails!
  </code></pre>
  
  <p>The above failed with <strong>pkcs11.exceptions.MechanismInvalid</strong> error. I tried using different mechanisms, but all of them resulted in the same error. What is interesting -- it seems that pkcs11 object allows me to at least invoke <em>decrypt</em> function without complaining that it is not supported. </p>
  
  <p>One more thing I should mention. I checked my certificate and saw that under Extension -> Certificate Key Usage, it says:</p>
  
  <pre><code>Critical
  Signing
  Key Encipherment
  </code></pre>
  
  <p>I read on the difference between <em>key encipherment</em> and <em>data encipherment</em> and learned that <em>key encipherment</em> is used to encrypt a secret (symmetric) key instead of data. Can it be the reason I can't use <em>encrypt</em> function for this token session? </p>
  
  <p>Any feedback would be greatly appreciated! </p>