4

I want to use python to encrypt some data and have come across pycrypto as a possible tool. In order to encrypt the data, I need to:

  1. Input passphrase string
  2. SHA-256 the string, giving key for AES-256
  3. Represent sensitive data as string of 9 digit characters (ascii), with leading ascii 0s if present (the data will always be in this format).
  4. Encrypt data string using AES-256, NO SALT, using PKCS7 padding from RFC2315, in ecb mode.
  5. Represent ciphertext as Base64 (RFC 4648), needing 24 characters

Using pycrypto, steps 1-3 are fairly easy. 4 is giving me a little bit of trouble. I'm not sure what PKCS7 padding is, and I am not sure how to ensure that the encryption is not using a SALT. I was hoping someone could point me in the right direction re: step 4.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Demetri Pananos
  • 6,770
  • 9
  • 42
  • 73
  • Possible duplicate of [Encrypt & Decrypt using PyCrypto AES 256](http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256) (see the pad and unpad functions) – Artjom B. Apr 04 '17 at 19:04
  • A salt has absolutely no meaning in step 4. Perhaps the author meant the initialization vector (IV), but that would not be available, because you're trying to use ECB which doesn't use an IV. Salt might have a meaning in step 2. *This proposed scheme is quite bad...* – Artjom B. Apr 04 '17 at 19:07
  • 2
    You should never use a simple hash function to protect your user's passwords. You need to use a strong hashing scheme like PBKDF2, bcrypt, scrypt and Argon2. Be sure to use a high cost factor/iteration count. It is common to choose the cost so that a single iteration takes at least 100ms. See more: [How to securely hash passwords?](http://security.stackexchange.com/q/211/45523) – Artjom B. Apr 04 '17 at 19:08
  • 1
    **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Apr 04 '17 at 19:08

3 Answers3

8

PyCrypto does not have inbuilt feature for padding. But it is quite easy to implement it. Note: PKCS7 Padding will add an extra byte block when the input is already the correct size, which this function does as well. PKCS#7 padding is explained here.

def pad(m):
    return m+chr(16-len(m)%16)*(16-len(m)%16)

KEY = sha256(passphrase).digest()  #returns 256 bit key
cipher = AES.new(KEY,AES.MODE_ECB) #creates a AES-256 instance using ECB mode
ciphertext = cipher.encrypt(pad(data)).encode('base64')

Hopefully, this is what you are looking for. During the process of Decryption, the unpad function might come handy.

def unpad(ct):
    return ct[:-ct[-1]]

In Python 3, the unpad function may need to cast (depending on usage), looking like this:

def unpad(ct):
    return ct[:-ord(ct[-1])]

P.S,

ECB mode of encryption is not cryptographic secure. Please use higher modes such as CBC, OFB or GCM.

GCM or Galois/Counter Mode provides both data confidentiality as well as authentication (Even for associated data, which need not be encrypted).

It is the most secure mode yet unless you use the same nonce twice

Community
  • 1
  • 1
Sayooj Samuel
  • 542
  • 5
  • 8
  • How would `pad` be used if the message is a bytearray? – Fusseldieb Sep 03 '20 at 14:40
  • @Fusseldieb Shown in the [this other answer](https://stackoverflow.com/a/70344303/589259) (yes, I know, late, but more for other readers). – Maarten Bodewes Jan 02 '22 at 19:30
  • 1
    **Warning**: above does not check the full padding, nor does it validate the last byte, which means that it is not detecting padding errors either. Now those should not be relied upon (use a MAC or authenticated cipher) but it is not how PKCS#7 unpadding should take place. It's easy but not **that** easy, Sayooj. – Maarten Bodewes Jan 02 '22 at 19:33
2

If the message is a bytearray

def pkcs7padding(data, block_size=16):
  if type(data) != bytearray and type(data) != bytes:
    raise TypeError("Only support bytearray/bytes !")
  pl = block_size - (len(data) % block_size)
  return data + bytearray([pl for i in range(pl)])

def pkcs5padding(data):
    return pkcs7padding(data, 8)
  • 1
    While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – holydragon Dec 14 '21 at 06:50
0

You might want to visit https://pycryptodome.readthedocs.io/en/latest/src/util/util.html?highlight=Cryppto.Util.Padding#module-Crypto.Util.Padding

pycryptodome has padding and unpadding functions

Roman Brito
  • 111
  • 2
  • 4