pythonpython-3.xencryptionpgpopenpgp

PGPy: encrypting and decrypting strings using passwords


I'm running into trouble encrypting and decrypting strings with the passphrase functionality using PGPy.

This works:

message = PGPMessage.new("42 is quite a pleasant number")
enc_message = message.encrypt("S00per_Sekr3t")
dec_message = enc_message.decrypt("S00per_Sekr3t")
print(dec_message.message)

This doesn't:

message = PGPMessage.new("42 is quite a pleasant number", cleartext=True)
enc_message = message.encrypt("S00per_Sekr3t")
dec_message = enc_message.decrypt("S00per_Sekr3t")
print(dec_message.message)

In fact, it results in a not implemented error:

Traceback (most recent call last):
  File "encrypt.py", line 42, in <module>
    enc = pgpy.PGPMessage.from_blob(encrypted).decrypt(args.password).message
  File "/home/soot/code/soot/playground-gen/env/lib/python3.8/site-packages/pgpy/pgp.py", line 910, in message
    if self.type == 'cleartext':
  File "/home/soot/code/soot/playground-gen/env/lib/python3.8/site-packages/pgpy/pgp.py", line 941, in type
    raise NotImplementedError
NotImplementedError

Doing a bit of poking around, it looks like the _message field of the decrypted message is empty (None). What am I doing wrong?


Solution

  • Exploring a little bit in line with my comment, creating a message with cleartext=True means that when we add a signature, like this:

    >>> msg = pgpy.PGPMessage.new('this is a test', cleartext=True)
    >>> msg |= key.sign(msg)
    

    We get a cleartext message with an attached signature:

    >>> print(msg)
    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA256
    
    this is a test
    -----BEGIN PGP SIGNATURE-----
    
    wsFzBAEBCAAdBQJim99qFiEEBIwoA4ecqC7e0I79tVIRi39z2Y8ACgkQtVIRi39z
    2Y+HsxAAoTk9D/4AcbSNtK4X4L7VxRof9YtV/1qVh26+FqSfgZiYa8vq8wF4JS18
    pdRB/Rqf3VFOTClzrdhcVrEJGFRUpQbCAAv+iRkHnknV6fNqCP9t729wtmcSDSoh
    jTa8wZldUuiB+64IoPjSAdKsJ1idN7hvU2dZcwBg+lakDFDLnQR/cjbHEGQot3BL
    CvNmn5n6U0k61r8LNfI7ygUZStEdIzYZgWgGvl2pjHgtVsVVwocfl8RV8UQWHHew
    CpRc0MrG01v2mdoKv+hqOfx1MVxLiqU6ExdIlQsSfHUwjJzIE4C8EdzhjChowCFc
    tzv+a9tS1CXpjqF6pvS34vvsx2fCcTlVXljhxM0cboRlwIzg7H6fU3pGoFRQyqDU
    Wdkr+2ffAJnOX0MK9nPO0Ow5oxc3oZX2E8Bhr87xT2iC7uuNBruiQU74ex2YkAgy
    xtYNUz+L4vqowQapuY7QkSCGtW9VdxJREwk1jHkpYQRnSCkCy1e8QGGAFFKaRlS6
    tuP5ok5YhcsmOPw9IBhg3vtS6o29C95CaiblO2/p0CiCY6g1iq9CklMMCWmrEPWa
    fvD78LKfvxJwd1zlhhBOftLRp42YVL5M8s8pwv2xLFJxkFk0LBOTZ/5NcOYKLG22
    IzygtvUFh6H9d/gbfkIbU0j6RzPq2/AaUxqFi2OT8GT40sPjnOs=
    =hYDm
    -----END PGP SIGNATURE-----
    

    Whereas if we create the message without cleartext=True:

    >>> msg = pgpy.PGPMessage.new('this is a test')
    >>> msg |= key.sign(msg)
    

    We get a signed message block instead:

    >>> print(msg)
    -----BEGIN PGP MESSAGE-----
    
    yMGhAQFbAqT9xA0DAAgBtVIRi39z2Y8AyxR1AGKb35Z0aGlzIGlzIGEgdGVzdMLB
    cwQAAQgAHQUCYpvfxxYhBASMKAOHnKgu3tCO/bVSEYt/c9mPAAoJELVSEYt/c9mP
    00YP/2zOqwwV6MxMOhhxARIIRvFKyu/z1tHGUvBh2ucEAasjJDW+tYO/r8knat2e
    GccnZzHMwlPKpWqGbF4AERzhZWFMfWIcFC+kvUTKogGtWKHaa+8TIyRXF1W3WJ95
    cM/rAIgWEHd/GF9vup5ny6o9ksZl826SMCtIau1/nkSuFndEMeyfvHQ3vxYxgFTV
    of+3vAOC9qn75YV4hKvTPbGhfG9uxQ79mKTz3+KV/vtk3fPbJuUnBKoxOsd9VPw1
    kN6alHInezQgr6wwmsLgPGpTnnEaMaV2i/VJtA/EKk2wGozPe8jbakYZdM7WlTNI
    mQBrSHIDCdNuI+6yNlvHvXweI9B4psPsSlsR7zVQk8yVfrUGm+GgFluSJ0R4NHJT
    U9HtmN5S8nBb/WY7IHzCjktadcfPM81P3OtADfm9olMtgpqCfCegHo8HD2qXtNda
    F6F7u61iBqNEk50zyM9WJJoS5BMNdEl1Nb38tin/AZYLECrbpcRuMbikKLYCInir
    dLHJyJl0ZS4REPqqDeU5vxclhd20oVRrUkXIfxng3JGOJGkR3ytEtbnN/YoXu+w6
    VwiTDZ6k07FBjDeLH0FdrtOiFySaXEEDbX9Khyg2wchs29wiKIMoRNf0kaQpMIq3
    YzKzRKgqduNr3MW50fLYSC92h48C2AW7GJoogaHdOKwqRity
    =rDbz
    -----END PGP MESSAGE-----
    

    I think that's the use of the cleartext parameter, and I think we see NotImplemented errors when trying to decrypt it because a "cleartext" encrypted message doesn't make sense.