0

I'm new to AWS lambda and encryption.
I have a raw string which needs to be first encoded using SHA 512 and then further encoded using AES 256 with salt.

I am able to encrypt to SHA 512 using hashlib

enStr = 'amdkasmd' #some random string
res = hashlib.sha512(enStr.encode()).hexdigest()

I want to further encrypt this using AES 256 algorithm in CBC mode with salt (initialization vector)

I tried doing this using pycryptodomex

from base64 import b64encode, b64decode
import hashlib
from Cryptodome.Cipher import AES
import os
from Cryptodome.Random import get_random_bytes

def encrypt(plain_text, password):
    # generate a random salt
    salt = get_random_bytes(AES.block_size)

    # use the Scrypt KDF to get a private key from the password
    private_key = hashlib.scrypt(
        password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # create cipher config
    cipher_config = AES.new(private_key, AES.MODE_GCM)

    # return a dictionary with the encrypted text
    cipher_text, tag = cipher_config.encrypt_and_digest(bytes(plain_text, 'utf-8'))
    return {
        'cipher_text': b64encode(cipher_text).decode('utf-8'),
        'salt': b64encode(salt).decode('utf-8'),
        'nonce': b64encode(cipher_config.nonce).decode('utf-8'),
        'tag': b64encode(tag).decode('utf-8')
    }


def decrypt(enc_dict, password):
    # decode the dictionary entries from base64
    salt = b64decode(enc_dict['salt'])
    cipher_text = b64decode(enc_dict['cipher_text'])
    nonce = b64decode(enc_dict['nonce'])
    tag = b64decode(enc_dict['tag'])
    

    # generate the private key from the password and salt
    private_key = hashlib.scrypt(
        password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # create the cipher config
    cipher = AES.new(private_key, AES.MODE_GCM, nonce=nonce)

    # decrypt the cipher text
    decrypted = cipher.decrypt_and_verify(cipher_text, tag)

    return decrypted

This worked on my local machine. I installed the packages to a directory on my local machine using

pip install <packages> -t . --no-user

and zipped the packages and added them to AWS layers.

but when i try to do the same on AWS LAMBDA i get an import error

[ERROR] OSError: Cannot load native module 'Cryptodome.Cipher._raw_ecb': Not found '_raw_ecb.cpython-39-x86_64-linux-gnu.so', Not found '_raw_ecb.abi3.so', Not found '_raw_ecb.so'
Traceback (most recent call last):
  File "/var/lang/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/var/task/lambda_function.py", line 7, in <module>
    from Cryptodome.Cipher import AES
  File "/opt/python/Cryptodome/Cipher/__init__.py", line 27, in <module>
    from Cryptodome.Cipher._mode_ecb import _create_ecb_cipher
  File "/opt/python/Cryptodome/Cipher/_mode_ecb.py", line 35, in <module>
    raw_ecb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ecb", """
  File "/opt/python/Cryptodome/Util/_raw_api.py", line 309, in load_pycryptodome_raw_lib
    raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts)))START RequestId: 17522507-0686-4f36-a104-f728c870b93e Version: $LATEST
2023-02-08T07:15:32.694Z 17522507-0686-4f36-a104-f728c870b93e Task timed out after 3.04 seconds

END RequestId: 17522507-0686-4f36-a104-f728c870b93e
REPORT RequestId: 17522507-0686-4f36-a104-f728c870b93e  Duration: 3039.25 ms    Billed Duration: 3000 ms    Memory Size: 128 MB Max Memory Used: 19 MB

Any help appreciated

Anirudh B M
  • 55
  • 1
  • 6

3 Answers3

0

You have used the PyCryptodome package which is not a default python package. So you have installed it on your local machine. That's why your code is working expected on the local machine.

But AWS Lambda doesn't provide external libraries/packages by default during its runtime. That means PyCruptodome is not available in Lambda. That's why you are getting errors in Lambda. To fix this you need to use AWS Lambda layers.

For an in-depth understanding, you can visit here https://www.geeksforgeeks.org/how-to-install-python-packages-for-aws-lambda-layers/

For can not loading issue you can check this module initialization error: Cannot load native module 'Crypto.Cipher._raw_ecb' at AWS lambda

0

There's a distinction between format encoding, encrypting & hashing. What's the goal of this process of hashing then encrypting? What kind of data is being worked on? Who needs access to the data afterwards?

Encoding, almost always, means transforming data from one readable format to another. Encoding is not generally a process intended to hide information so that it remains secret.

Encrypting something on the other hand, means transforming data in such a way so as to guarantee, with almost perfect (relevant) probability, that only by using the correct secret key material can the information be intelligibly reconstructed, even partially, after having been encrypted.

With hashing, there is usually no expectation for anyone to reconstruct the data, or even fundamentally be able to (but they might get lucky by guessing inputs many-many times).

First, you'll need a secret key if you'll be doing encryption. But, if you expect to decrypt, you'll need a secure way to store the secret key (or recompute it). Second, even if you have a secret key to do decryption, you won't be able to read the contents of what went into the hash function (but someone dedicated enough might be able to guess by bruteforce or precomputed tables). Third, CBC mode is not a mode which provides data integrity or validation. Fourth, if the enStr is a password, this process you've outlined is not an adequate solution to protect it.

To do authenticated encryption in python of some non-password data, with a nonce, under some context_key & additionally authenticating some optional context information, one could very easily use the cryptography library, which often comes packaged with python in OS distros. ...It's not clear why you need to hash enStr first, so I won't be considering or analyzing that part of the process.

import hmac
from hashlib import sha256
from secrets import token_bytes
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305

root_key = token_bytes(64)  # you have to protect this somehow
nonce = token_bytes(12)  # use only once for encryption
context = b"why-what-where-when-who-how"  # change per context
context_key = hmac.new(root_key, nonce + context, sha256).digest()
context_cipher = ChaCha20Poly1305(context_key)

data = b"amdkasmd"
encrypted_data = context_cipher.encrypt(nonce, data, context)
ciphertext = nonce + encrypted_data  # you often shouldn't need to send
                                     # the context, because the receiver
                                     # already knows the context since
                                     # they are within the context

Always use caution & follow best practices when dealing with secrets. I hope this was helpful!

aiootp
  • 154
  • 4
  • I am trying to hash the enStr using SHA 256 this will be stored in lets say table1, in another table2 i will be storing the encrypted hash, when i want to access details , first i plan to decrypt the encrypted hash and use that to access details in table1 – Anirudh B M Feb 09 '23 at 06:32
0

The problem was how aws lambda interprets packages.
I was downloading the packages on a windows machine and adding them to layers in AWS.
I downloaded the packages through a linux machine, zipped and uploaded to the aws layers.

Anirudh B M
  • 55
  • 1
  • 6