balena / python-smime

S/MIME encoder in pure python
Apache License 2.0
18 stars 17 forks source link

AttributeError #4

Closed tuck1s closed 6 years ago

tuck1s commented 6 years ago

I've tried the following, both with my native interpreter installation and a fresh VirtualEnv. I'm getting the following with the example code from the README

$ python3 sparkySecure.py 
Traceback (most recent call last):
  File "sparkySecure.py", line 12, in <module>
    print(smime.encrypt('\n'.join(message), pem.read()))
AttributeError: module 'smime' has no attribute 'encrypt'

Checking the package:

$ pip3 show smime
Name: smime
Version: 0.0.3
Summary: Python S/MIME Toolkit
Home-page: https://github.com/balena/python-smime
Author: G. B. Versiani
Author-email: guibv@yahoo.com
License: Apache License (2.0)
Location: /usr/local/lib/python3.7/site-packages
Requires: asn1crypto, pycrypto
Required-by: 
tuck1s commented 6 years ago

Suspecting this might have been a recent Python 3.x issue, I tried a Linux machine with Python 3.5. pip install smime gives the following errors

  building 'Crypto.Hash._MD2' extension
  creating build/temp.linux-x86_64-3.4
  creating build/temp.linux-x86_64-3.4/src
  gcc -pthread -DDYNAMIC_ANNOTATIONS_ENABLED=1 -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -std=c99 -O3 -fomit-frame-pointer -Isrc/ -I/usr/include/python3.4m -c src/MD2.c -o build/temp.linux-x86_64-3.4/src/MD2.o
  src/MD2.c:31:20: error: Python.h: No such file or directory
  src/MD2.c:131: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  In file included from src/MD2.c:147:
  src/hash_template.c:48: error: expected specifier-qualifier-list before ‘PyObject_HEAD’
  src/hash_template.c:59: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘PyTypeObject’
  src/hash_template.c: In function ‘newALGobject’:
  src/hash_template.c:69: warning: implicit declaration of function ‘PyObject_New’
  src/hash_template.c:69: error: expected expression before ‘ALGobject’
  src/hash_template.c: At top level:
  src/hash_template.c:76: error: expected ‘)’ before ‘*’ token
  src/hash_template.c:91: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:110: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:122: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:162: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:188: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:190: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ALG_methods’
  src/hash_template.c:199: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:225: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ALGtype’
  src/hash_template.c:271: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  src/hash_template.c:304: error: array type has incomplete element type
  src/hash_template.c:305: error: ‘PyCFunction’ undeclared here (not in a function)
  src/hash_template.c:305: error: expected ‘}’ before ‘ALG_new’
  src/hash_template.c: In function ‘init_MD2’:
  src/hash_template.c:339: error: ‘PyObject’ undeclared (first use in this function)
  src/hash_template.c:339: error: (Each undeclared identifier is reported only once
  src/hash_template.c:339: error: for each function it appears in.)
  src/hash_template.c:339: error: ‘m’ undeclared (first use in this function)
  src/hash_template.c:351: error: ‘ALGtype’ undeclared (first use in this function)
  src/hash_template.c:351: error: ‘PyType_Type’ undeclared (first use in this function)
  src/hash_template.c:352: warning: implicit declaration of function ‘Py_InitModule’
  src/hash_template.c:356: error: ‘o’ undeclared (first use in this function)
  src/hash_template.c:356: warning: implicit declaration of function ‘PyInt_FromLong’
  src/hash_template.c:356: warning: implicit declaration of function ‘PyDict_SetItemString’
  src/hash_template.c:356: warning: implicit declaration of function ‘PyModule_GetDict’
  src/hash_template.c:356: warning: implicit declaration of function ‘Py_DECREF’
  src/hash_template.c:360: warning: implicit declaration of function ‘PyErr_Occurred’
  src/hash_template.c:361: warning: implicit declaration of function ‘Py_FatalError’
  error: command 'gcc' failed with exit status 1
tuck1s commented 6 years ago

I wonder if it's related to: https://stackoverflow.com/questions/50080459/failed-installing-pycrypto/50099842

balena commented 6 years ago

Hello @tuck1s, sorry for the delay to answer.

Definitely the library will have trouble with Python 3.3 upwards. As indicated in the README.md file, it supports Python 2.7 and 3.3.

In order to support newer Python versions, we have to get rid of these old dependencies. I didn't find a good substitute yet, if you can indicate other options to perform the same PyCrypto operations, let me know.

Regards, Balena.

tuck1s commented 6 years ago

The Stack Overflow article mentions pycryptodome. There is also https://github.com/pyca/cryptography. Not sure if those help. I'm going to explore those today and see if I can make it work with the MIME handling in https://docs.python.org/3.7/library/email.parser.html?highlight=email%20message_from_string#module-email.parser Oh and thank you for your answer - that was actually quick!

balena commented 6 years ago

Dear @tuck1s, I just released a version 0.0.4 using https://github.com/pyca/cryptography instead of PyCrypto. It is not in PyPI yet, please let me know if it works for you, so I'm going to release it in PyPI later on.

tuck1s commented 6 years ago

Thanks @balena - I'm not sure of the best way to install straight from Github, but I cloned the project then moved the smime dir under my test project, that seems to run. I'll build some test messages and try them towards Thunderbird.

tuck1s commented 6 years ago

hmm looks like my key files might have been corrupt. Never mind - it now works!

$ openssl smime -decrypt -in ex3.eml -inkey boblumreeker\@gmailcom_private.pem 
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Now you see me.
tuck1s commented 6 years ago

Is there a way to sign as well as encrypt a message?

balena commented 6 years ago

@tuck1s, my test was the following:

I executed the same code it is in the README.md using one of the RSA example keys available in smime/testdata. It gave me the following output:

To: "Alice" <alice@foo.com>
From: "Bob" <bob@bar.com>
Subject: A message from python
MIME-Version: 1.0
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7m

MIIBdgYJKoZIhvcNAQcDoIIBZzCCAWMCAQAxgb4wgbsCAQAwJjASMRAwDgYDVQQD
EwdDYXJsUlNBAhBGNGvHgABWvBHTbi7EELOwMAsGCSqGSIb3DQEBAQSBgGfgP5LI
41a8kb6/wY35juXXW0BaF+FBIEn1xpXosM3BHq4VcD77Epb+CnfxZLy4lpf/we6H
vyjm1cietfvZLGQxfCS/itJu/FulBFqP0Zq2pEcaEZUXPky7Vb70B9WfYMAZVlEc
QEzSz/KBO3txP/CEbh3fyJc73AkzSzIBuiLKMIGcBgkqhkiG9w0BBwEwHQYJYIZI
AWUDBAEqBBA+iq7Y2bJTpx7SJ7ONpH8CgHDZ1EmLONl7XaJCj06MJryI+UaN+ek+
E7asegHMgHK/y3Fx+rwOVIfrwaATkKTzruItNrTtJ3aci4mrq3IjG6wu/NTfeqao
wP1Q1xURhHTiehOiCRor+ezTqllHaEUWDHLISy0cL4kHr2AUi7E4kEPz

Then I created a smime.p7m.base64 as follows:

MIIBdgYJKoZIhvcNAQcDoIIBZzCCAWMCAQAxgb4wgbsCAQAwJjASMRAwDgYDVQQD
EwdDYXJsUlNBAhBGNGvHgABWvBHTbi7EELOwMAsGCSqGSIb3DQEBAQSBgGfgP5LI
41a8kb6/wY35juXXW0BaF+FBIEn1xpXosM3BHq4VcD77Epb+CnfxZLy4lpf/we6H
vyjm1cietfvZLGQxfCS/itJu/FulBFqP0Zq2pEcaEZUXPky7Vb70B9WfYMAZVlEc
QEzSz/KBO3txP/CEbh3fyJc73AkzSzIBuiLKMIGcBgkqhkiG9w0BBwEwHQYJYIZI
AWUDBAEqBBA+iq7Y2bJTpx7SJ7ONpH8CgHDZ1EmLONl7XaJCj06MJryI+UaN+ek+
E7asegHMgHK/y3Fx+rwOVIfrwaATkKTzruItNrTtJ3aci4mrq3IjG6wu/NTfeqao
wP1Q1xURhHTiehOiCRor+ezTqllHaEUWDHLISy0cL4kHr2AUi7E4kEPz

Then I used openssl to transform the BASE64 output to binary, or in other terms, get the DER format out of the BASE64 encoded body:

openssl base64 -d -in smime.p7m.base64 -out smime.p7m

And then I made the following:

openssl smime -decrypt -in smime.p7m -inform der -inkey alice-private-key.pem

And took the following output:

Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Now you see me.
balena commented 6 years ago

I wrote in the README.md that OpenSSL expects that the BASE64 content be enclosed in -----BEGIN PKCS7----- and -----END PKCS7-----. So if you want to use the input as PEM (PKCS#7), you need to create a smime.p7m file in the following way:

-----BEGIN PKCS7-----
MIIBdgYJKoZIhvcNAQcDoIIBZzCCAWMCAQAxgb4wgbsCAQAwJjASMRAwDgYDVQQD
EwdDYXJsUlNBAhBGNGvHgABWvBHTbi7EELOwMAsGCSqGSIb3DQEBAQSBgGfgP5LI
41a8kb6/wY35juXXW0BaF+FBIEn1xpXosM3BHq4VcD77Epb+CnfxZLy4lpf/we6H
vyjm1cietfvZLGQxfCS/itJu/FulBFqP0Zq2pEcaEZUXPky7Vb70B9WfYMAZVlEc
QEzSz/KBO3txP/CEbh3fyJc73AkzSzIBuiLKMIGcBgkqhkiG9w0BBwEwHQYJYIZI
AWUDBAEqBBA+iq7Y2bJTpx7SJ7ONpH8CgHDZ1EmLONl7XaJCj06MJryI+UaN+ek+
E7asegHMgHK/y3Fx+rwOVIfrwaATkKTzruItNrTtJ3aci4mrq3IjG6wu/NTfeqao
wP1Q1xURhHTiehOiCRor+ezTqllHaEUWDHLISy0cL4kHr2AUi7E4kEPz
-----END PKCS7-----

Then again the OpenSSL smime command:

openssl smime -decrypt -in smime.p7m -inform pem -inkey alice-private-key.pem

Gives the same result:

Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Now you see me.
balena commented 6 years ago

Is there a way to sign as well as encrypt a message?

Oh, I was willing to implement this... But time was short. Anyway, if you encrypt, you're already guaranteeing it's you.