strong crypto moved to pysnmpcrypto
parent
bc2654205b
commit
24a7988766
10
CHANGES.txt
10
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
|
||||
-----------------------------------
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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'
|
||||
|
|
8
setup.py
8
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',
|
||||
|
|
Loading…
Reference in New Issue