summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2018-02-24 21:42:19 +0100
committerGitHub <noreply@github.com>2018-02-24 21:42:19 +0100
commitf38ae966c0ebb53a24af4f8d1484b9b01233e8ab (patch)
tree60fbb40e681f20579611e83e6a2d445d27076bfb
parentbc2654205b7b566bd4e2caa8c5c703ec03a140a0 (diff)
parent24a7988766551038be2c65a33f10173a7a6d559d (diff)
downloadpysnmp-git-f38ae966c0ebb53a24af4f8d1484b9b01233e8ab.tar.gz
Merge pull request #135 from etingof/pysnmpcrypto-dependency
Strong crypto moved to pysnmpcrypto
-rw-r--r--CHANGES.txt10
-rw-r--r--README.md5
-rw-r--r--THANKS.txt1
-rw-r--r--docs/source/docs/pysnmp-architecture.rst2
-rw-r--r--docs/source/download.rst19
-rw-r--r--pysnmp/__init__.py2
-rw-r--r--pysnmp/crypto/__init__.py131
-rw-r--r--pysnmp/crypto/aes.py67
-rw-r--r--pysnmp/crypto/des.py74
-rw-r--r--pysnmp/crypto/des3.py67
-rw-r--r--pysnmp/proto/errind.py4
-rw-r--r--pysnmp/proto/secmod/eso/priv/des3.py42
-rw-r--r--pysnmp/proto/secmod/rfc3414/priv/des.py44
-rw-r--r--pysnmp/proto/secmod/rfc3826/priv/aes.py40
-rw-r--r--requirements.txt5
-rw-r--r--setup.py8
16 files changed, 115 insertions, 406 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c55ddc16..1542cace 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,9 +1,13 @@
-Revision 4.?.?, released 2018-??-??
+Revision 5.0.0, released 2018-03-??
-----------------------------------
-- Crypto abstraction layer added to allow use of pyca/cryptography instead of Pycryptodome
-- Dependencies modified to use pyca/cryptography for supported Python versions
+- SNMPv3 crypto operations that require external dependencies
+ made dependent on the optional external
+ package -- pysnmpcrypto.
+- By switching to pysnmpcrypto, pysnmp effectively migrates from
+ PyCryptodomex to pyca/cryptography whenever available on the
+ platform.
Revision 4.4.4, released 2018-01-03
-----------------------------------
diff --git a/README.md b/README.md
index 18b6509e..e85e1ac3 100644
--- a/README.md
+++ b/README.md
@@ -57,9 +57,8 @@ to download and install PySNMP along with its dependencies:
* [PyASN1](http://snmplabs.com/pyasn1/)
* [PySMI](http://snmplabs.com/pysmi/) (required for MIB services only)
-* A supported cryptography backend (required only if SNMPv3 encryption is in use)
- * [pyca/cryptography](http://cryptography.io/) for Python 2.7 and 3.4+
- * [PyCryptodomex](https://pycryptodome.readthedocs.io) for Python 2.4-2.6 and 3.2-3.3
+* Optional [pysnmpcrypto](https://github.com/etingof/pysnmpcrypto) package
+ whenever strong SNMPv3 encryption is desired
Besides the library, command-line [SNMP utilities](https://github.com/etingof/snmpclitools)
written in pure-Python could be installed via:
diff --git a/THANKS.txt b/THANKS.txt
index b44833af..d27461f0 100644
--- a/THANKS.txt
+++ b/THANKS.txt
@@ -30,5 +30,6 @@ Laurelin of Middle Earth
Robert Reese
Olivier Verriest
Eugene M. Kim
+Matt Bullock
Thanks to Python Software Foundation for granting financial support
for the project.
diff --git a/docs/source/docs/pysnmp-architecture.rst b/docs/source/docs/pysnmp-architecture.rst
index 4256e12c..020cc5a5 100644
--- a/docs/source/docs/pysnmp-architecture.rst
+++ b/docs/source/docs/pysnmp-architecture.rst
@@ -9,7 +9,7 @@ We can look at PySNMP's internal structure from the view point of
SNMP protocol evolution. SNMP was evolving for many years from
a relatively simple way to structure and retrieve data (SNMPv1/v2c)
all the way to extensible and modularized framework that supports
-strong crypto out-of-the-box (SNMPv3).
+strong SNMPv3 crypto (with optional pysnmpcrypto package).
In the order from most ancient SNMP services to the most current ones,
what follows are different layers of PySNMP APIs:
diff --git a/docs/source/download.rst b/docs/source/download.rst
index 69413e4a..87743486 100644
--- a/docs/source/download.rst
+++ b/docs/source/download.rst
@@ -42,19 +42,16 @@ In case you are installing PySNMP on an off-line system, the following
packages need to be downloaded and installed for PySNMP to become
operational:
-* `PyASN1 <https://pypi.python.org/pypi/pyasn1>`_,
- used for handling ASN.1 objects
-* `PySNMP <https://pypi.python.org/pypi/pysnmp/>`_,
+* `pysnmp <https://pypi.python.org/pypi/pysnmp/>`_,
SNMP engine implementation
-
-Optional, but recommended:
-
-* `PyCryptodomex <https://pypi.python.org/pypi/pycryptodomex/>`_,
- used by SNMPv3 crypto features
-* `PySMI <https://pypi.python.org/pypi/pysmi/>`_ for automatic
+* `pyasn1 <https://pypi.python.org/pypi/pyasn1>`_,
+ used for handling ASN.1 objects
+* `pysmi <https://pypi.python.org/pypi/pysmi/>`_ for automatic
MIB download and compilation. That helps visualizing more SNMP objects
-* `Ply <https://pypi.python.org/pypi/ply/>`_, parser generator
- required by PySMI
+
+Optional:
+* `pysnmpcrypto <https://pypi.python.org/pypi/pysnmpcrypto/>`_,
+ for strong SNMPv3 crypto support
The installation procedure for all the above packages is as follows
(on UNIX-based systems):
diff --git a/pysnmp/__init__.py b/pysnmp/__init__.py
index 168d8d7c..9cd704f4 100644
--- a/pysnmp/__init__.py
+++ b/pysnmp/__init__.py
@@ -1,5 +1,5 @@
# http://www.python.org/dev/peps/pep-0396/
-__version__ = '4.4.4'
+__version__ = '5.0.0'
# backward compatibility
version = tuple([int(x) for x in __version__.split('.')])
majorVersionId = version[0]
diff --git a/pysnmp/crypto/__init__.py b/pysnmp/crypto/__init__.py
deleted file mode 100644
index 2431cd91..00000000
--- a/pysnmp/crypto/__init__.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""Backend-selecting cryptographic logic to allow migration to pyca/cryptography
-without immediately dropping support for legacy minor Python versions.
-
-On installation, the correct backend dependency is selected based on the Python
-version. Versions that are supported by pyca/cryptography use that backend; all
-other versions (currently 2.4, 2.5, 2.6, 3.2, and 3.3) fall back to Pycryptodome.
-"""
-from pysnmp.proto import errind, error
-CRYPTOGRAPHY = 'cryptography'
-CRYPTODOME = 'Cryptodome'
-
-# Determine the available backend. Always prefer cryptography if it is available.
-try:
- import cryptography
- backend = CRYPTOGRAPHY
-except ImportError:
- try:
- import Cryptodome
- backend = CRYPTODOME
- except ImportError:
- backend = None
-
-
-def _cryptodome_encrypt(cipher_factory, plaintext, key, iv):
- """Use a Pycryptodome cipher factory to encrypt data.
-
- :param cipher_factory: Factory callable that builds a Pycryptodome Cipher instance based
- on the key and IV
- :type cipher_factory: callable
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- encryptor = cipher_factory(key, iv)
- return encryptor.encrypt(plaintext)
-
-
-def _cryptodome_decrypt(cipher_factory, ciphertext, key, iv):
- """Use a Pycryptodome cipher factory to decrypt data.
-
- :param cipher_factory: Factory callable that builds a Pycryptodome Cipher instance based
- on the key and IV
- :type cipher_factory: callable
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- decryptor = cipher_factory(key, iv)
- return decryptor.decrypt(ciphertext)
-
-
-def _cryptography_encrypt(cipher_factory, plaintext, key, iv):
- """Use a cryptography cipher factory to encrypt data.
-
- :param cipher_factory: Factory callable that builds a cryptography Cipher instance based
- on the key and IV
- :type cipher_factory: callable
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- encryptor = cipher_factory(key, iv).encryptor()
- return encryptor.update(plaintext) + encryptor.finalize()
-
-
-def _cryptography_decrypt(cipher_factory, ciphertext, key, iv):
- """Use a cryptography cipher factory to decrypt data.
-
- :param cipher_factory: Factory callable that builds a cryptography Cipher instance based
- on the key and IV
- :type cipher_factory: callable
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- decryptor = cipher_factory(key, iv).decryptor()
- return decryptor.update(ciphertext) + decryptor.finalize()
-
-
-_DECRYPT_MAP = {
- CRYPTOGRAPHY: _cryptography_decrypt,
- CRYPTODOME: _cryptodome_decrypt
-}
-_ENCRYPT_MAP = {
- CRYPTOGRAPHY: _cryptography_encrypt,
- CRYPTODOME: _cryptodome_encrypt
-}
-
-
-def generic_encrypt(cipher_factory_map, plaintext, key, iv):
- """Encrypt data using the available backend.
-
- :param dict cipher_factory_map: Dictionary that maps the backend name to a cipher factory
- callable for that backend
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- if backend is None:
- raise error.StatusInformation(
- errorIndication=errind.encryptionError
- )
- return _ENCRYPT_MAP[backend](cipher_factory_map[backend], plaintext, key, iv)
-
-
-def generic_decrypt(cipher_factory_map, ciphertext, key, iv):
- """Decrypt data using the available backend.
-
- :param dict cipher_factory_map: Dictionary that maps the backend name to a cipher factory
- callable for that backend
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- if backend is None:
- raise error.StatusInformation(
- errorIndication=errind.decryptionError
- )
- return _DECRYPT_MAP[backend](cipher_factory_map[backend], ciphertext, key, iv)
diff --git a/pysnmp/crypto/aes.py b/pysnmp/crypto/aes.py
deleted file mode 100644
index 20e91e7f..00000000
--- a/pysnmp/crypto/aes.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""
-Crypto logic for RFC3826.
-
-https://tools.ietf.org/html/rfc3826
-"""
-from pysnmp.crypto import backend, CRYPTODOME, CRYPTOGRAPHY, generic_decrypt, generic_encrypt
-
-if backend == CRYPTOGRAPHY:
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
-elif backend == CRYPTODOME:
- from Cryptodome.Cipher import AES
-
-
-def _cryptodome_cipher(key, iv):
- """Build a Pycryptodome AES Cipher object.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: AES Cipher instance
- """
- return AES.new(key, AES.MODE_CFB, iv, segment_size=128)
-
-
-def _cryptography_cipher(key, iv):
- """Build a cryptography AES Cipher object.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: AES Cipher instance
- :rtype: cryptography.hazmat.primitives.ciphers.Cipher
- """
- return Cipher(
- algorithm=algorithms.AES(key),
- mode=modes.CFB(iv),
- backend=default_backend()
- )
-
-
-_CIPHER_FACTORY_MAP = {
- CRYPTOGRAPHY: _cryptography_cipher,
- CRYPTODOME: _cryptodome_cipher
-}
-
-
-def encrypt(plaintext, key, iv):
- """Encrypt data using AES on the available backend.
-
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- return generic_encrypt(_CIPHER_FACTORY_MAP, plaintext, key, iv)
-
-
-def decrypt(ciphertext, key, iv):
- """Decrypt data using AES on the available backend.
-
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- return generic_decrypt(_CIPHER_FACTORY_MAP, ciphertext, key, iv)
diff --git a/pysnmp/crypto/des.py b/pysnmp/crypto/des.py
deleted file mode 100644
index 12ce611b..00000000
--- a/pysnmp/crypto/des.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-Crypto logic for RFC3414.
-
-https://tools.ietf.org/html/rfc3414
-"""
-from pysnmp.crypto import backend, CRYPTODOME, CRYPTOGRAPHY, generic_decrypt, generic_encrypt
-
-if backend == CRYPTOGRAPHY:
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
-elif backend == CRYPTODOME:
- from Cryptodome.Cipher import DES
-
-
-def _cryptodome_cipher(key, iv):
- """Build a Pycryptodome DES Cipher object.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: DES Cipher instance
- """
- return DES.new(key, DES.MODE_CBC, iv)
-
-
-def _cryptography_cipher(key, iv):
- """Build a cryptography DES(-like) Cipher object.
-
- .. note::
-
- pyca/cryptography does not support DES directly because it is a seriously old, insecure,
- and deprecated algorithm. However, triple DES is just three rounds of DES (encrypt,
- decrypt, encrypt) done by taking a key three times the size of a DES key and breaking
- it into three pieces. So triple DES with des_key * 3 is equivalent to DES.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: TripleDES Cipher instance providing DES behavior by using provided DES key
- :rtype: cryptography.hazmat.primitives.ciphers.Cipher
- """
- return Cipher(
- algorithm=algorithms.TripleDES(key * 3),
- mode=modes.CBC(iv),
- backend=default_backend()
- )
-
-
-_CIPHER_FACTORY_MAP = {
- CRYPTOGRAPHY: _cryptography_cipher,
- CRYPTODOME: _cryptodome_cipher
-}
-
-
-def encrypt(plaintext, key, iv):
- """Encrypt data using DES on the available backend.
-
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- return generic_encrypt(_CIPHER_FACTORY_MAP, plaintext, key, iv)
-
-
-def decrypt(ciphertext, key, iv):
- """Decrypt data using DES on the available backend.
-
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- return generic_decrypt(_CIPHER_FACTORY_MAP, ciphertext, key, iv)
diff --git a/pysnmp/crypto/des3.py b/pysnmp/crypto/des3.py
deleted file mode 100644
index 1ccb9aeb..00000000
--- a/pysnmp/crypto/des3.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""
-Crypto logic for Reeder 3DES-EDE for USM (Internet draft).
-
-https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00
-"""
-from pysnmp.crypto import backend, CRYPTODOME, CRYPTOGRAPHY, generic_decrypt, generic_encrypt
-
-if backend == CRYPTOGRAPHY:
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
-elif backend == CRYPTODOME:
- from Cryptodome.Cipher import DES3
-
-
-def _cryptodome_cipher(key, iv):
- """Build a Pycryptodome DES3 Cipher object.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: DES3 Cipher instance
- """
- return DES3.new(key, DES3.MODE_CBC, iv)
-
-
-def _cryptography_cipher(key, iv):
- """Build a cryptography TripleDES Cipher object.
-
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: TripleDES Cipher instance
- :rtype: cryptography.hazmat.primitives.ciphers.Cipher
- """
- return Cipher(
- algorithm=algorithms.TripleDES(key),
- mode=modes.CBC(iv),
- backend=default_backend()
- )
-
-
-_CIPHER_FACTORY_MAP = {
- CRYPTOGRAPHY: _cryptography_cipher,
- CRYPTODOME: _cryptodome_cipher
-}
-
-
-def encrypt(plaintext, key, iv):
- """Encrypt data using triple DES on the available backend.
-
- :param bytes plaintext: Plaintext data to encrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Encrypted ciphertext
- :rtype: bytes
- """
- return generic_encrypt(_CIPHER_FACTORY_MAP, plaintext, key, iv)
-
-
-def decrypt(ciphertext, key, iv):
- """Decrypt data using triple DES on the available backend.
-
- :param bytes ciphertext: Ciphertext data to decrypt
- :param bytes key: Encryption key
- :param bytes IV: Initialization vector
- :returns: Decrypted plaintext
- :rtype: bytes
- """
- return generic_decrypt(_CIPHER_FACTORY_MAP, ciphertext, key, iv)
diff --git a/pysnmp/proto/errind.py b/pysnmp/proto/errind.py
index d660af54..1629ecce 100644
--- a/pysnmp/proto/errind.py
+++ b/pysnmp/proto/errind.py
@@ -175,13 +175,13 @@ authenticationFailure = AuthenticationFailure('Authenticator mismatched')
class UnsupportedAuthProtocol(ErrorIndication):
pass
-unsupportedAuthProtocol = UnsupportedAuthProtocol('Authentication protocol is not supprted')
+unsupportedAuthProtocol = UnsupportedAuthProtocol('Authentication protocol is not supported')
class UnsupportedPrivProtocol(ErrorIndication):
pass
-unsupportedPrivProtocol = UnsupportedPrivProtocol('Privacy protocol is not supprted')
+unsupportedPrivProtocol = UnsupportedPrivProtocol('Privacy protocol is not supported')
class UnknownSecurityName(ErrorIndication):
diff --git a/pysnmp/proto/secmod/eso/priv/des3.py b/pysnmp/proto/secmod/eso/priv/des3.py
index bf39a8ff..51f7ad75 100644
--- a/pysnmp/proto/secmod/eso/priv/des3.py
+++ b/pysnmp/proto/secmod/eso/priv/des3.py
@@ -5,15 +5,6 @@
# License: http://snmplabs.com/pysnmp/license.html
#
import random
-from pysnmp.crypto import des3
-from pysnmp.proto.secmod.rfc3414.priv import base
-from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
-from pysnmp.proto.secmod.rfc3414 import localkey
-from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
-from pysnmp.proto import errind, error
-from pyasn1.type import univ
-from pyasn1.compat.octets import null
-
try:
from hashlib import md5, sha1
except ImportError:
@@ -23,6 +14,21 @@ except ImportError:
md5 = md5.new
sha1 = sha.new
+try:
+ from pysnmpcrypto import des3, PysnmpCryptoError
+
+except ImportError:
+ PysnmpCryptoError = AttributeError
+ des3 = None
+
+from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
+from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
+from pysnmp.proto import errind, error
+from pyasn1.type import univ
+from pyasn1.compat.octets import null
+
random.seed()
@@ -117,7 +123,14 @@ class Des3(base.AbstractEncryptionService):
privParameters = univ.OctetString(salt)
plaintext = dataToEncrypt + univ.OctetString((0,) * (8 - len(dataToEncrypt) % 8)).asOctets()
- ciphertext = des3.encrypt(plaintext, des3Key, iv)
+
+ try:
+ ciphertext = des3.encrypt(plaintext, des3Key, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
return univ.OctetString(ciphertext), privParameters
@@ -138,6 +151,13 @@ class Des3(base.AbstractEncryptionService):
)
ciphertext = encryptedData.asOctets()
- plaintext = des3.decrypt(ciphertext, des3Key, iv)
+
+ try:
+ plaintext = des3.decrypt(ciphertext, des3Key, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
return plaintext
diff --git a/pysnmp/proto/secmod/rfc3414/priv/des.py b/pysnmp/proto/secmod/rfc3414/priv/des.py
index b874162a..f64abc8a 100644
--- a/pysnmp/proto/secmod/rfc3414/priv/des.py
+++ b/pysnmp/proto/secmod/rfc3414/priv/des.py
@@ -5,15 +5,6 @@
# License: http://snmplabs.com/pysnmp/license.html
#
import random
-from pysnmp.crypto import des
-from pysnmp.proto.secmod.rfc3414.priv import base
-from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
-from pysnmp.proto.secmod.rfc3414 import localkey
-from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
-from pysnmp.proto import errind, error
-from pyasn1.type import univ
-from sys import version_info
-
try:
from hashlib import md5, sha1
except ImportError:
@@ -23,6 +14,22 @@ except ImportError:
md5 = md5.new
sha1 = sha.new
+from sys import version_info
+
+try:
+ from pysnmpcrypto import des, PysnmpCryptoError
+
+except ImportError:
+ PysnmpCryptoError = AttributeError
+ des = None
+
+from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
+from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
+from pysnmp.proto import errind, error
+from pyasn1.type import univ
+
random.seed()
@@ -107,7 +114,14 @@ class Des(base.AbstractEncryptionService):
# 8.1.1.2
plaintext = dataToEncrypt + univ.OctetString((0,) * (8 - len(dataToEncrypt) % 8)).asOctets()
- ciphertext = des.encrypt(plaintext, desKey, iv)
+
+ try:
+ ciphertext = des.encrypt(plaintext, desKey, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
# 8.3.1.3 & 4
return univ.OctetString(ciphertext), privParameters
@@ -133,5 +147,11 @@ class Des(base.AbstractEncryptionService):
errorIndication=errind.decryptionError
)
- # 8.3.2.6
- return des.decrypt(encryptedData.asOctets(), desKey, iv)
+ try:
+ # 8.3.2.6
+ return des.decrypt(encryptedData.asOctets(), desKey, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
diff --git a/pysnmp/proto/secmod/rfc3826/priv/aes.py b/pysnmp/proto/secmod/rfc3826/priv/aes.py
index 82fa0da5..7d796b1a 100644
--- a/pysnmp/proto/secmod/rfc3826/priv/aes.py
+++ b/pysnmp/proto/secmod/rfc3826/priv/aes.py
@@ -5,14 +5,6 @@
# License: http://snmplabs.com/pysnmp/license.html
#
import random
-from pyasn1.type import univ
-from pysnmp.crypto import aes
-from pysnmp.proto.secmod.rfc3414.priv import base
-from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
-from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
-from pysnmp.proto.secmod.rfc3414 import localkey
-from pysnmp.proto import errind, error
-
try:
from hashlib import md5, sha1
except ImportError:
@@ -22,6 +14,20 @@ except ImportError:
md5 = md5.new
sha1 = sha.new
+try:
+ from pysnmpcrypto import aes, PysnmpCryptoError
+
+except ImportError:
+ PysnmpCryptoError = AttributeError
+ aes = None
+
+from pyasn1.type import univ
+from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
+from pysnmp.proto.secmod.rfc3414 import localkey
+from pysnmp.proto import errind, error
+
random.seed()
@@ -110,7 +116,13 @@ class Aes(base.AbstractEncryptionService):
# PyCrypto seems to require padding
dataToEncrypt = dataToEncrypt + univ.OctetString((0,) * (16 - len(dataToEncrypt) % 16)).asOctets()
- ciphertext = aes.encrypt(dataToEncrypt, aesKey, iv)
+ try:
+ ciphertext = aes.encrypt(dataToEncrypt, aesKey, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
# 3.3.1.4
return univ.OctetString(ciphertext), univ.OctetString(salt)
@@ -133,5 +145,11 @@ class Aes(base.AbstractEncryptionService):
# PyCrypto seems to require padding
encryptedData = encryptedData + univ.OctetString((0,) * (16 - len(encryptedData) % 16)).asOctets()
- # 3.3.2.4-6
- return aes.decrypt(encryptedData.asOctets(), aesKey, iv)
+ try:
+ # 3.3.2.4-6
+ return aes.decrypt(encryptedData.asOctets(), aesKey, iv)
+
+ except PysnmpCryptoError:
+ raise error.StatusInformation(
+ errorIndication=errind.unsupportedPrivProtocol
+ )
diff --git a/requirements.txt b/requirements.txt
index 76ab7775..be42ce0a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,3 @@
pysmi
-pycryptodomex; python_version < '2.7'
-cryptography; python_version == '2.7'
-pycryptodomex; python_version == '3.2'
-pycryptodomex; python_version == '3.3'
-cryptography; python_version >= '3.4'
pyasn1>=0.2.3
ordereddict; python_version < '2.7'
diff --git a/setup.py b/setup.py
index f5a81a78..f2e6358c 100644
--- a/setup.py
+++ b/setup.py
@@ -55,12 +55,7 @@ if py_version < (2, 4):
print("ERROR: this package requires Python 2.4 or later!")
sys.exit(1)
-if py_version < (2, 7) or (py_version >= (3, 0) and py_version < (3, 4)):
- crypto_lib = 'pycryptodomex'
-else:
- crypto_lib = 'cryptography'
-
-requires = ['pyasn1>=0.2.3', 'pysmi', crypto_lib]
+requires = ['pyasn1>=0.2.3', 'pysmi']
if py_version < (2, 7):
requires.append('ordereddict')
@@ -112,7 +107,6 @@ params.update({
'pysnmp.carrier.twisted.dgram',
'pysnmp.carrier.asyncio',
'pysnmp.carrier.asyncio.dgram',
- 'pysnmp.crypto',
'pysnmp.entity',
'pysnmp.entity.rfc3413',
'pysnmp.entity.rfc3413.oneliner',